# Datenkapselung



## thor_norsk (29. Dez 2021)

Guten Tag,

ich habe folgende Aufgabe erhalten und bin mir nicht sicher, ob ich die Aufgabe richtig gelöst habe?

Aufgabe: Sie haben folgende Klassenvereinbarungen in getrennten Quelltextdateien:

[CODE lang="java" title="Datenkapselung"]package tiere;

public class Katze {

    private int gewicht;
    private int farbe;
    private int groesse;
    }

package tiere;

public class Elternkatze extends Katze {

    private int kinderzahl;       
    }[/CODE]

Die Klasse Elternkatze soll auf die Instanzvariable gewicht der Klasse Katze zugreifen können.
Welche Möglichkeiten kennen Sie, diesen Zugriff zu ermöglichen? Bewerten Sie diese Möglichkeiten bitte auch.
Achten Sie dabei auf die Datenkapselung.
Ein Tipp: Sie sollten mindestens drei verschiedene Varianten nennen können. Zwei hängen direkt mit der Vereinbarung der Instanzvariablen zusammen, die dritte dagegen nicht.

Meine Lösungsvorschläge:
Mit dem Zugriff, verstehe ich sowohl gewicht setzen, und abfragen? 


1 Möglichkeit ) private weg lassen, allerdings verletze ich die Regeln der Datenkapselung?
2 Möglichkeit ) Mit 2 Methoden erweitern die auf public gesetzt sind ?
3 Möglichkeit ) Öffentlicher Kostruktor, zum beispiel: 
// öffentlicher Konstruktor
public Katze (int gewicht) {
    setGewicht(gewicht);
    }
// die Methode ist als private deklariert!
private void setGewicht(int gewicht) {
   this.gewicht = gewicht;
   }

4 Möglichkeit) Habe ich mir gedacht, ersetzte private durch public, aber ich denke ist nicht Sinn und Zweck der Aufgabe oder ?


----------



## Mart (29. Dez 2021)

thor_norsk hat gesagt.:


> 1 Möglichkeit ) private weg lassen, allerdings verletze ich die Regeln der Datenkapselung?


wenn du private weg lässt und nichts davor stehen hast hast du die Package sichtbarkeit die beiden klassen sind in demselben package... muss abgewogen werden ob es erlaubt ist dass jeder im package in der katze rum wurschteln darf


thor_norsk hat gesagt.:


> 2 Möglichkeit ) Mit 2 Methoden erweitern die auf public gesetzt sind ?


public bringt dir hier gar nichts, da es die datenkapselung komplett zerstört, weil du dann noch mehr sichtbarkeit als wie mit package sichtbarkeit hergibst


thor_norsk hat gesagt.:


> 3 Möglichkeit ) Öffentlicher Kostruktor, zum beispiel:


nein

was wäre mit

PROTECTED ... du bist in vererbung unterwegs
=> protected getter vllt sogar
=> kinderanzahl passt dann auf private da die Katze

```
protected final int getGewicht(){

return this.gewicht;

}
```
somit hat die eltern katze zugang aufs lesen des gewichts aber keine Schreibe Rechte => problematik des gewchts ist nur in der Katze klasse nicht in der Vererbungs klasse
so hättest du minimale Rechte fürs gewicht meines erachtens
minimales Recht kann man *als gute datenkapselung* interpretieren... stell ich mal so in den Raum


----------



## thor_norsk (29. Dez 2021)

So wie du beschrieben hast, habe ich nur Lesezugriff ? Ich dachte ich muss auch Schreibzugriff ermöglichen? Weil unter Zugriffsrecht verstehe ich Lese und Schreibzugriff.


----------



## temi (29. Dez 2021)

thor_norsk hat gesagt.:


> Zwei hängen direkt mit der Vereinbarung der Instanzvariablen zusammen


Das wäre vermutlich package private (deine 1. Möglichkeit) und protected.

Ein öffentlicher Getter wäre noch in Ordnung, bei Settern bin ich generell eher vorsichtig. Der Objektzustand sollte sich normalerweise über fachliche Methoden ändern. Im Fall des Gewichts der Katze, wäre das dann etwas wie fresse().


----------



## Oneixee5 (29. Dez 2021)

Als Kapselung oder Datenkapselung bezeichnet man den kontrollierten Zugriff auf Methoden bzw. Attribute von Klassen. Klassen können den internen Zustand anderer Klassen nicht in unerwarteter Weise lesen oder ändern. Es gibt demnach für die Aufgabe folgende Lösungsmöglichkeiten:
1 Möglichkeit ) private weg lassen, allerdings verletze ich die Regeln der Datenkapselung? - Ist richtig und: Nein, du willst den Zugriff ermöglichen oder einschränken, du gibst also die Regeln vor, du definierst die Regel.
2 Möglichkeit ) Mit 2 Methoden erweitern die auf public gesetzt sind ? - Ist vollkommen richtig
3 Möglichkeit ) Öffentlicher Kostruktor - ist falsch: bei 1 beziehst du dich auf die Standard-Sichbarkeit, das ist aber nicht die einzige Möglichkeit. Beziehe dich besser auf das Schlüsselwort protected.


----------



## Mart (29. Dez 2021)

thor_norsk hat gesagt.:


> So wie du beschrieben hast, habe ich nur Lesezugriff ? Ich dachte ich muss auch Schreibzugriff ermöglichen? Weil unter Zugriffsrecht verstehe ich Lese und Schreibzugriff.


datenkapselung = schutz der daten

wenn jeder lesen und schreiben kann weist du dann noch ob der datensatz richtig ist? 

deswegen minimale rechte, wenn du schreibne MUSST schreibt man einen setter ansonsten nicht ... ende aus...

falls du schreibe und lese zugriff hast kannst gleich das attribut auf public setzen ...... weil du es dann eh nicht mehr weis was überhaupt los ist ..nett gesagt

get und set methode zu haben macht schon sinnn aber setter sollte man mit bedacht einsetzen


----------



## thor_norsk (29. Dez 2021)

1) Gefällt mir nicht, weil in der Aufgabestellung darauf hingewiesen wird, man solle auf Datenkapselung achten! Einfach private weg lassen
funktioniert zwar aber Datenkapselung ist hin oder ?
2) Sage ich danke!
3) mit protected hätte ich selber darauf kommen müssen, sage ich nochmals danke!

Gibt es eine andere Möglichkeit ?


----------



## temi (29. Dez 2021)

thor_norsk hat gesagt.:


> Gefällt mir nicht, weil in der Aufgabestellung darauf hingewiesen wird, man solle auf Datenkapselung achten! Einfach private weg lassen
> funktioniert zwar aber Datenkapselung ist hin oder ?


Es kann durchaus gewollt und sinnvoll sein, dass Klassen im selben Package Zugriff haben dürfen. Das ist situationsbedingt. Die Kapselung ist schlechter als bei private, aber besser als bei public.


----------



## thor_norsk (29. Dez 2021)

OK. Ich denke private weg lassen wäre richtig , da in der Aufgabestellung darauf hingewiesen wird!


----------



## temi (29. Dez 2021)

thor_norsk hat gesagt.:


> OK. Ich denke private weg lassen wäre richtig , da in der Aufgabestellung darauf hingewiesen wird!


Du sollst die Möglichkeiten ja auch bewerten. Insofern können sie ja wohl nicht alle gleichwertig sein.

EDIT: Darum kann man hier gerne auch weniger sinnvolle Möglichkeiten erwähnen und entsprechend (vor allem hinsichtlich der Kapselung) bewerten.


----------



## Mart (29. Dez 2021)

thor_norsk hat gesagt.:


> OK. Ich denke private weg lassen wäre richtig , da in der Aufgabestellung darauf hingewiesen wird!


es gibt
public
package
auf die attribute

public package protected getter und setter
injection
reflection
und was auch noch alles .. .kannst ja mal reflection hinschreiben dann passt der code mit private


----------



## Oneixee5 (29. Dez 2021)

Mart hat gesagt.:


> .. .kannst ja mal reflection hinschreiben dann passt der code mit private


Ich hoffe so etwas schreibt er nicht hin.


----------



## Mart (29. Dez 2021)

Oneixee5 hat gesagt.:


> Ich hoffe so etwas schreibt er nicht hin.


wäre zwar leicht getrollt aber es geht 

beurteilung : könnte fragwürdig sein


----------



## Robert Zenz (29. Dez 2021)

thor_norsk hat gesagt.:


> 1 Möglichkeit ) private weg lassen, allerdings verletze ich die Regeln der Datenkapselung?


`package-private` ist der Teufel wenn es um API-Design geht! Es ist so einfach damit Konstellationen zu machen welche weder erweiterbar noch verwendbar sind, dass ist furchtbar. Vergiss am besten dass es das gibt. `protected` waere dann die Sichtbarkeit der Wahl.

Also, es gibt die klassische Java-Klasse, wo alle Felder einfach nur `private` sind, aber ich sehe keinen bis wenige Nachteile darin die Felder einfach `protected` zu machen. Der Vorteil hier ist das ableitende Klassen tatsaechliche die Moeglichkeit haben die Klasse sinnvoll zu erweitern. Der Nachteil ist, dass jemand eventuell deinen internen Zustand vergiftet, und dann bei dir im Bug-Tracker aufschlaegt mit einer dummen Frage (sehen wir's ein, das passiert nie).

`protected` bedeutet auch das Zugriff aus dem selben Package moeglich ist...vergiss das einfach, das ist nur praktisch fuer Unit-Tests. Ist fuer den eigentlichen Anwendungsfall genauso schlecht wie `package-private`.



thor_norsk hat gesagt.:


> 2 Möglichkeit ) Mit 2 Methoden erweitern die auf public gesetzt sind ?


Ja, klassisches Zugriffsbeispiel:


```
public class Example {
    private int value = 0;
   
    public Example() {
        super();
    }
    
    public int getValue() {
        return value;
    }
    
    public void setValue(int value) {
        this.value = value;
    }
}
```

Hierbei ist zu beachten dass man nun ueber den Setter bestimmte Werte bestimmen (und auch mit Fehler quittieren) kann, also wenn du zum Beispiel einen Wertebereich durchsetzen willst. Nach aussen kann eine ableitende Klasse deine Getter/Setter aber immer noch ueberschreiben, und damit auch deinen internen Zustand vergiften wenn du diese Methoden verwendest. Sagen wir mal:


```
public class Example {
    private int value = 0;
   
    public Example() {
        super();
    }
    
    public int getValue() {
        return value;
    }
    
    public void setValue(int value) {
        verifyValueIsInRangeOrThrow(value);
       
        this.value = value;
    }

    public int performOperation() {
        return somethingSomethingWithValue(getValue());
    }
}
```

Wenn sich jetzt eine Klasse ableitet und diese dann `getValue()` ueberschreibt, wird deine Operation den Wert verwenden welche diese ausliefert:


```
public class ExtendedExample {
    public ExtendedExample() {
        super();
    }
    
    @Override
    public int getValue() {
        return valueTotallyOutsideAcceptableRange;
    }
}
```

Damit kann man dann immer noch deinen internen Zustand zu einem gewissen Grad vergiften. Auch sind die Getter/Setter `public`, was eventuell nicht gewuenscht ist.

Als Alternative dazu kannst du die Getter/Setter `protected` machen, um nur ableitenden Klassen Zugriff zu erlauben, zum Beispiel wenn du den Wert nur zum Zugriff und nicht zum aendern nach aussen fuehren willst:


```
public class Example {
    private int value = 0;
   
    public Example() {
        super();
    }
    
    public int getValue() {
        return value;
    }
    
    protected void setValue(int value) {
        verifyValueIsInRangeOrThrow(value);
       
        this.value = value;
    }
}
```

Damit koennen nun sich ableitende Klassen einen neuen Wert wuenschen, aber sie koennen immer noch die Methoden ueberschreiben. Wenn du jetzt wirklich gezielten und kontrollierten Zugriff erlauben willst, machst du die Getter/Setter am besten `final`:


```
public class Example {
    private int value = 0;
   
    public Example() {
        super();
    }
    
    public final int getValue() {
        return value;
    }
    
    protected final void setValue(int value) {
        verifyValueIsInRangeOrThrow(value);
       
        this.value = value;
    }
}
```

Damit hast du nun kontrollierten Zugriff, und kannst immer genau sagen dass der Wert welche zurueckgegeben oder verwendet wird, innerhalb des von dir gewuenschten Bereiches liegt. Gleichzeitig koennen ableitende Klassen auch den Zustand setzen, was bei nur einer `private` nicht moeglich waere.



thor_norsk hat gesagt.:


> 3 Möglichkeit ) Öffentlicher Kostruktor, zum beispiel:


Ja, wenn sich die Werte nie wieder im Laufe des Lebens der Instanz aendern sollen, akzeptabel. Man muss aber aufpassen dass dann die Konstruktoren nicht dann zwanzig Variablen uebernimmt, dann muss man sich was neues ueberlegen.

In diesem Beispiel weniger, aber auch hier kann man eine Kombination aus `public` und `protected` Konstruktoren machen um ableitenden Klassen die Chance zu geben den Wert zu bestimmen:


```
public class Example {
    private int value = 0;
   
    public Example() {
        this(DEFAULT_VALUE);
    }
    
    protected Example(int value) {
        super();

        verifyValueIsInRangeOrThrow(value);
        
         this.value = value;
    }
}
```

In deinem Fall wuerde aber ein `public` Konstruktor welche alle Werte uebernimmt (und validiert) zielfuehrend wenn ich das richtig sehe.



thor_norsk hat gesagt.:


> 4 Möglichkeit) Habe ich mir gedacht, ersetzte private durch public, aber ich denke ist nicht Sinn und Zweck der Aufgabe oder ?


Es ist eine Moeglichkeit, und es kann Sinn machen, aber es ist denke ich nicht im Sinne der Aufgabe, ja.

Also Klassen wie zum Beispiel:


```
public class Example {
    public int value = 0;
   
    public Example() {
        super();
    }
}
```

Koennen Sinn machen, aber ziemlich immer ist es besser den Zugriff auf die eine oder andere Art zu kontrollieren, wie du ja bereits festgestellt hast. Der Vorteil daran Methoden (Getter/Setter) zu stellen, ist der dass du Logik nachruesten kannst ohne dass die verwender der API etwas aendern muessen. Die rufen weiterhin die Getter/Setter auf, und du machst darin einfach Dinge, zum Beispiel validieren oder veraendern des Werts.


----------



## Mart (29. Dez 2021)

Robert Zenz hat gesagt.:


> aber ziemlich immer ist es besser den Zugriff auf die eine oder andere Art zu kontrollieren, wie du ja bereits festgestellt hast


ganz klar über reflection und alles private lassen xD


----------



## Oneixee5 (29. Dez 2021)

Mart hat gesagt.:


> ganz klar über reflection und alles private lassen xD


Ist das trollen und provozieren? Lass den Blödsinn.


----------



## Mart (29. Dez 2021)

Oneixee5 hat gesagt.:


> Ist das trollen und provozieren? Lass den Blödsinn.





> Sie sollten mindestens drei verschiedene Varianten nennen können.


----------



## thor_norsk (29. Dez 2021)

Zuerst möchte ich mich bedanken. Wir haben bis jetzt nur Sichtbarkeit (public, private, protected) besprochen und die Erweiterung mit den Methoden. Ich werde lieber keine Experimente machen und halte mich lieber am Lehrplan.


----------



## Mart (30. Dez 2021)

reflection ist auch jenseits von gut und böse für diese aufgabe aber es würde gehen


----------



## thor_norsk (30. Dez 2021)

Also : Ich habe nochmal nachgelesen, ich könnte wenn ich euch richtig verstanden habe, als 4 Möglichkeit ,,package'' für Attribut wählen?
 z.B. public class Katze {
package int gewicht;

......

}

Da Beide Klassen sind in gleichem Paket befinden wäre möglich?


----------



## Mart (30. Dez 2021)

den "package" modifier gibts so NICHT

package sichtbarkeit drückst du aus in dem du NICHTS als modifier davor schreibst also 


> int gewicht;


----------



## thor_norsk (30. Dez 2021)

Super.


----------

