2010-05-26 5 views
31

Ich habe ein Objekt, das einige Daten in einer Liste speichert. Die Implementierung könnte sich später ändern und ich möchte die interne Implementierung dem Endbenutzer nicht offen legen. Der Benutzer muss jedoch in der Lage sein, diese Sammlung von Daten zu ändern und darauf zuzugreifen. Zur Zeit habe ich so etwas wie dieses:Ist es besser, Liste oder Sammlung zu verwenden?

public List<SomeDataType> getData() { 
    return this.data; 
} 

public void setData(List<SomeDataType> data) { 
    this.data = data; 
} 

Bedeutet dies, dass ich die internen Implementierungsdetails erlaubt haben, auszutreten? Sollte ich das stattdessen tun?

public Collection<SomeDataType> getData() { 
    return this.data; 
} 

public void setData(Collection<SomeDataType> data) { 
    this.data = new ArrayList<SomeDataType>(data); 
} 
+9

Eine Sache zu beachten ist, dass, wenn Sie die tatsächliche Sammlung oder Liste zurückgeben, Sie jemand anderen zu tun, was sie wollen, einschließlich Löschen von Elementen oder sogar das Löschen der ganzen Sache. Sie können besser einen nicht änderbaren Wrapper oder eine Kopie der Liste zurückgeben. –

+1

@PaulTomblin wahr, aber es ist ein bisschen Overkill und künstliche Overhead für das System. Nicht änderbare Wrapper sind sinnvoll, wenn Sie mit Objekten arbeiten, die von Persistenz-Middleware verwaltet werden, und dies auch nur in seltenen Fällen. – comeGetSome

+0

@comeGetSome, deshalb habe ich gesagt "kann" anstatt "muss". Es würde vom Anwendungsfall abhängen - wenn ich eine API für andere verwenden würde, würde ich eine Kopie oder einen Wrapper zurückgeben. Wenn es für mich selbst oder für vertrauenswürdige Kollegen wäre, würde ich ein großes "NICHT ÄNDERN DIESEN WERT" in die Javadocs setzen und es dabei belassen. –

Antwort

24

Es kommt nur, möchten Sie Ihre Benutzer in die Daten zu indizieren können? Wenn ja, verwende Liste. Bei beiden handelt es sich um Schnittstellen, sodass Sie die Implementierungsdetails nicht verlieren. Sie müssen lediglich die erforderliche Mindestfunktionalität festlegen.

0

Wenn ich mit der Verschleierung der internen Darstellung meiner Daten für einen externen Benutzer beschäftigt wäre, würde ich entweder XML oder JSON verwenden. Wie auch immer, sie sind ziemlich universell.

+0

bedeutet das immer String Rückgabetyp? – erdogany

+0

Natürlich. XML und JSON sollen ziemlich universell sein und was könnte universeller sein als eine Zeichenkette? – Cyberherbalist

+2

Nun, wenn ich Daten zwischen Apps übergebe, werde ich eine Codierung dieser Art verwenden. Aber wenn ich über einen Rückgabewert von einer Funktion spreche ... wandle es in XML um, gebe es als String zurück, und dann muss der Aufrufer das XML analysieren? Das ist eine Menge Komplexität und Overhead, nur um ein Array zurückzugeben. – Jay

1

Ja, Ihre erste Alternative führt zu Implementierungsdetails, wenn es nicht Teil Ihres Schnittstellenvertrags ist, dass die Methode immer eine Liste zurückgibt. Außerdem ist das Erlauben von Benutzercode zum Ersetzen Ihrer Sammlungsinstanz etwas gefährlich, da sich die Implementierung, die sie übergeben, möglicherweise nicht wie erwartet verhält.

Natürlich hängt alles davon ab, wie sehr Sie Ihren Benutzern vertrauen. Wenn du die Python-Philosophie nimmst, dass "wir hier alle Erwachsenen zustimmen", dann ist die erste Methode in Ordnung. Wenn Sie denken, dass Ihre Bibliothek von unerfahrenen Entwicklern verwendet wird und Sie alles tun müssen, um sie zu "babysitten" und sicherzustellen, dass sie nichts falsch machen, dann ist es besser, sie nicht die Sammlung zu setzen und nicht einmal zurückzukehren die eigentliche Sammlung. Übergeben Sie stattdessen eine (oberflächliche) Kopie davon.

+1

java.util.Collections enthält statische Methoden wie unmodiableList(), die Sammlungen einfach so umbrechen, dass alle Methoden, die die Sammlung ändern würden, stattdessen Fehler zurückgeben. Da es sich bei der Instanziierung der Wrapper um eine Operation mit konstanter Zeit handelt, ist es vorzuziehen, auch eine flache Kopie zu erstellen (welche sich der Clientcode selbst machen kann, wenn er eine veränderbare Sammlung benötigt). –

0

Es hängt davon ab, welche Garantien Sie dem Benutzer bieten möchten. Wenn die Daten sequenziell sind, so dass die Reihenfolge der Elemente wichtig ist und Sie Duplikate zulassen, verwenden Sie eine Liste. Wenn die Reihenfolge der Elemente keine Rolle spielt und Duplikate zulässig sind oder nicht, verwenden Sie eine Sammlung. Da Sie tatsächlich die zugrunde liegende Sammlung zurückgeben, sollten Sie nicht sowohl eine get- als auch eine set-Funktion haben, nur eine get-Funktion, da die zurückgegebene Sammlung mutiert sein kann. Außerdem ermöglicht die Bereitstellung einer Set-Funktion, dass die Art der Sammlung vom Benutzer geändert wird, während Sie wahrscheinlich möchten, dass der bestimmte Typ von Ihnen gesteuert wird.

5

Die Verwendung des allgemeinsten Typs, der Sammlung, ist am sinnvollsten, es sei denn, es gibt einen expliziten Grund, den spezifischeren Typ - Liste zu verwenden. Aber was auch immer Sie tun, wenn dies eine API für den öffentlichen Konsum ist, sollten Sie in der Dokumentation sehen, was sie tut; wenn es eine flache Kopie der Sammlung zurückgibt, sag es.

7

Beim Zurückgeben einer Implementierung einer Schnittstelle oder Klasse in einer hohen Hierarchie lautet die Faustregel, dass der deklarierte Rückgabetyp die HÖCHSTE Ebene sein sollte, die die Mindestfunktionalität bereitstellt, die Sie dem Aufrufer garantieren möchten. und dass der Anrufer vernünftigerweise benötigt. Angenommen, Sie geben eine ArrayList zurück. ArrayList implementiert unter anderem List und Collection. Wenn Sie erwarten, dass der Aufrufer die Funktion "get (int x)" verwenden muss, um eine Sammlung zurückzugeben, müssen Sie eine Liste oder eine ArrayList zurückgeben. Solange Sie keinen Grund sehen, warum Sie Ihre Implementierung ändern sollten, um etwas anderes als eine Liste zu verwenden - sagen wir ein Set - dann ist die richtige Antwort, eine Liste zurückzugeben. Ich bin mir nicht sicher, ob es irgendeine Funktion in ArrayList gibt, die nicht in List ist, aber wenn es welche gibt, würde das gleiche Argument zutreffen. Auf der anderen Seite haben Sie, nachdem Sie eine Liste anstelle einer Sammlung zurückgegeben haben, Ihre Implementierung in gewissem Umfang gesperrt. Je weniger Sie in Ihre API investieren, desto weniger Einschränkungen werden Sie für zukünftige Verbesserungen vorsehen.

(In der Praxis habe ich fast immer eine Liste, in solchen Situationen zurückkehren, und es hat mich nie verbrannt. Aber ich sollte wohl wirklich eine Sammlung zurück.)

9

Unabhängig von der Fähigkeit, Index in die Liste über Liste .get (int), haben die Benutzer (oder Sie) die Erwartung, dass sich die Elemente der Sammlung in einer zuverlässigen und vorhersehbaren Reihenfolge befinden? Kann die Sammlung ein Vielfaches des gleichen Artikels haben? Beides sind Erwartungen an Listen, die für allgemeinere Sammlungen nicht üblich sind. Dies sind die Tests, die ich verwende, wenn ich festlege, welche Abstraktion für den Endbenutzer verfügbar sein soll.

14

Die Rückgabe einer Liste entspricht der Programmierung für die am besten geeignete Schnittstelle.

Das Zurückgeben einer Sammlung würde für den Benutzer Mehrdeutigkeit verursachen, da eine zurückgegebene Auflistung entweder Set, List oder Queue sein kann.