So kapseln Sie ein Array in Java

8

Ich beginne mit Java und lerne etwas über Setter, Getters und Encapsulation. Ich habe ein sehr einfaches Programm, zwei Klassen:

  • Container hat ein privates int-Array ( numArray ) mit seinem Setter & amp; Getter.

  • Main erstellt ein Container -Objekt und verwendet es in totalArray method.

%Vor%

Problem: Ich kann das private int-Array durch den Getter ändern, ich weiß, weil getNumArray einen Verweis auf numArray zurückgibt, nicht das Array selbst. Wenn ich an einem einzelnen Element des Arrays interessiert wäre, würde ich einen Getter mit einem Indexwert erstellen, aber ich möchte das gesamte Array für die Methode totalArray .

Wie kann ich verhindern, dass numArray aus seiner Klasse heraus modifiziert wird?

    
Setwarn 05.01.2010, 15:04
quelle

8 Antworten

8

Alles, was Sie tun können, um zu verhindern, dass Leute Ihr Array ändern, ist, eine Kopie davon im Getter bereitzustellen.

%Vor%

Auf diese Weise können andere Methoden ihre eigene Kopie des Arrays ändern, aber wenn sie den Getter erneut aufrufen, erhalten sie die ursprüngliche Version unverändert. Nur das von Ihnen angegebene setNumArray() kann Ihr internes Array tatsächlich ändern.

Wenn Sie den Container vollständig blockieren möchten, müssen Sie andernfalls Arrays löschen und ein unveränderliches Objekt verwenden. Einige Bibliotheken bieten unveränderbare Listen oder verwenden Sammlungen.unmodifizierbareListe .

    
glmxndr 05.01.2010, 15:10
quelle
6

Wenn Sie ein Array zurückgeben möchten, würden Sie es klonen:

%Vor%

In einer öffentlichen API sollten Sie sicher sein, dies den Aufrufern klar zu dokumentieren (wirklich egal, ob sie ein Array bekommen, das den Status der Klasse ändert oder nicht - sie müssen es wissen).

    
Yishai 05.01.2010 15:11
quelle
3

Normalerweise würden Sie sich die Schnittstelle ansehen, die Sie Anrufern Ihrer Klasse bereitstellen möchten.

Methoden wie:

%Vor%

sind die Dinge, die Sie in Ihrer Containerklasse bereitstellen würden. Sie interagieren dann im Auftrag des Aufrufers mit dem privaten Array.

Wenn Sie das gesamte Array zurückgeben wollen, ohne Änderungen zuzulassen, könnten Sie das Array in ein neues kopieren und die Kopie zurückgeben.

Wenn Sie stattdessen die Java-Auflistungsklassen anstelle des primitiven Arrays verwenden, stellen sie eine unmodifizierbare XXX () -Methode bereit (z. B. Collections.unmodifiableList(myList) ), die einen schreibgeschützten Wrapper um die Auflistung bereitstellt.

    
Paolo 05.01.2010 15:08
quelle
0

Encapsulation ist der Prozess zum Ausblenden der Implementierung. Ob die Sammlung ihre Daten in einem Array speichert oder nicht, ist ein Implementierungsdetail. Wenn es gekapselt war, sollte es möglich sein, es in einen anderen Speichertyp zu ändern.

Gerade die Tatsache, dass Sie den Status (oder abgeleiteten Zustand) als Getter und Setter offen legen, bricht die Kapselung und impliziert, dass Sie einen abstrakten Datentyp statt einer echten objektorientierten Klasse implementieren. Ein ArrayList ist beispielsweise ein Datentyp, der keine echte Verkapselung des Verhaltens in einer Anwendung darstellt. Ob dies gewünscht ist, hängt davon ab, wie und wo der Typ verwendet wird.

Ich würde entweder Container implementieren Iterable<Integer> für externe Interaktionen verwenden, wenn es sich nur um einen Containerdatentyp handelt, oder eine interne Iteratormethode bereitstellen, an die Sie einen Besucher übergeben, wenn es als gekapselte Klasse gedacht ist. Wenn es sich um einen abstrakten Datentyp handelt, sollten Sie unbedingt die integrierten Typen wie int[] oder List<Integer> verwenden.

    
Pete Kirkham 05.01.2010 16:00
quelle
0

Es gibt noch einen anderen Weg, der keine Kopie des Arrays macht, aber andere Nachteile hat. Ich würde es für sehr große Arrays verwenden:

%Vor%     
sinharaj 16.06.2012 08:56
quelle
0
  

Wie man ein Array in Java einkapselt

Die Frage mag klar genug sein, aber ich denke, der Punkt von OOP ist, eine Klasse als eine Entity zu entwerfen , die dieses Array manipuliert und seine eigene api.

Wenn Sie persistent sind, geben Sie einen Klon des Arrays / eine defensive Kopie zurück. für einfache Fälle stark>.

    
MrNobody 14.10.2017 00:23
quelle
0

Ich möchte einen anderen Ansatz vorschlagen als alle Antworten, die ich hier gesehen habe. Es ist praktisch, wenn Sie an Kapselung denken, um auch an die Regel zu denken: "Fragen Sie kein Objekt nach seinen Daten, bitten Sie ein Objekt, seine Daten für Sie zu verwenden".

Sie haben mich nicht für numArray verwendet. Ich werde so tun, als ob Ihr Ziel darin besteht, einen numerischen "Vektor" aus Mathe (kein Java-Vektor) zu erstellen.

Sie erstellen also eine NumericVector-Klasse, die ein Double-Array enthält. Ihr NumericVector würde Methoden wie multiplyByScalar(double scalar) und addVector (NumericVector secondVector) haben, um Elemente hinzuzufügen.

Ihr internes Array ist vollständig gekapselt - es entkommt nie. Jede durchgeführte Operation wird in Ihrer NumericVector-Klasse über diese "Geschäftsmethoden" ausgeführt. Wie zeigen Sie es nach der Bedienung an? Lassen Sie NumericVector NumericVector.toString() überschreiben, damit es korrekt ausgegeben wird, oder schreiben Sie eine "Controller" -Klasse, um Daten von Ihrem Modell (NumbericVector) in Ihre Ansicht (GUI) zu übertragen. Dies erfordert möglicherweise eine Möglichkeit, Elemente von Ihrem NumericVector zu streamen.

Dies weist auch auf einige Dinge hin, die vermieden werden sollten: Sie erstellen nicht automatisch Setter und Getter, sie unterbrechen die Kapselung. Sie brauchen oft Getter, aber wie andere hier schon gesagt haben, sollten Sie Ihren Getter dazu bringen, eine unveränderliche Version des Arrays zurückzugeben. Versuchen Sie auch, Ihre Klassen möglichst unveränderbar zu machen. Die oben erwähnte Methode numericVector.addVector(NumericVector secondVector) sollte wahrscheinlich nicht numericVector ändern, sondern einen neuen NumericVector mit der Lösung zurückgeben.

Der Fall, in dem dies (und OO im Allgemeinen) oft scheitert, sind Bibliotheken - wenn Sie wirklich Ihrem Array ein wenig Funktionalität hinzufügen wollen, es aber immer noch als Allzweck-Array belassen. In diesem Fall kümmert sich Java normalerweise nicht um die Kapselung, es fügt einfach eine Hilfsmethode / Klasse hinzu, die Dinge zur Sammlung / zum Array tun kann (siehe das "Arrays" -Objekt für eine Reihe toller Beispiele).

>     
Bill K 13.10.2017 23:49
quelle
0

Eine speichereffiziente Möglichkeit dies zu tun ist ...

%Vor%

Dadurch kann ImmutableList die korrekte Anzahl von Elementen im Backing-Array von List festlegen und die Anzahl der erstellten Zwischenobjekte reduzieren.

    
Eric 14.10.2017 03:43
quelle

Tags und Links