# Klassen Vererbung und Zugriff auf innere private Variable



## berliner (30. Mrz 2009)

Hallo,

vielleicht kann mir jemand bei diesem (hier stark vereinfachten) Problem helfen:

Es existiert eine Klasse A, welche eine private Variable _X hat. Ich kann diese Klasse vom Code her nicht verändern, sie muss also als fest angenommen werden. Ausserdem sind innerhalb von A Funktionen, die auf _X zugreifen. 

Ich muss jetzt die Funktionalität von A via extend in B erweitern. In B muss ich den Wert von _X ändern können. 

Wie bekomme ich Zugriff auf die private Variable von A aus B?

Wenn ich die Sichtbarkeit von _X änder auf public funktioniert via super._X alles problemlos. Aber das ist leider keine Option. 

[highlight=Java]
public abstract class A
{

// [...]   

   private String _X = new String();

// [...]   

}
[/highlight]

[highlight=Java]
public class B extends A {

//[...]

    protected B()
   {     
      super._X = "blubb";
   }

//[...]

}
[/highlight]

Vielen Dank für jede Hilfe im Voraus und Grüße
Der Berliner


----------



## hdi (30. Mrz 2009)

Wenn Klasse A keine Methode zur Verfügung stellt, die B aufrufen kann, ist dies nicht möglich.
A muss also einen Setter anbieten, oder zumindest eine entsprechende Methode, die
protected oder default ist, je nachdem wo dein B liegt.

EDIT 3 : *HILFE!*:
Weder private Member-Methoden, noch -Variablen werden vererbt.
So laut Definition. Aber ich hab grad n totales Blackout... Ein BMW hat doch auch einen ps-Wert,
selbst wenn das in der Klasse Auto private gestellt wurde ?! Der Zugriff ist was anderes,
aber ich meine die Member-Variable wird doch geerbt?
Hilfe... überall steht: *private members are NOT inherited*.
Wtf... das heisst ja dass ich beim Aufruf eines getPs() auf einem BMW einen Runtime-Error kriegen müsste. Weil es die Variable nicht gibt... 
Weil das nicht der Fall ist, müsste ja dann quasi jeder BMW intern ein eigenes Auto-Objekt
mitschleppen?!
Oh man, Brett vor'm Kopf?


----------



## diggaa1984 (30. Mrz 2009)

public getter und setter wären ne maßnahme, bzw protected, je nach notwendigkeit.

da die variable private ist, kommst auch in der geerbten klasse nicht ran. Protected würde gehen


----------



## berliner (30. Mrz 2009)

@hdi: Schön nicht ganz alleine verwirrt zu sein ;-) Ist das Auto euer Standardbeispiel?

@diggaa1984: "public getter und setter" würde aber nur als Veränderung von A gehen?! In B haben die leider keinen Zugriff. Leider kann ich A nicht verändern, da ich da auf die Umgebung zugreife die übertragbar bleiben muss.


----------



## hdi (30. Mrz 2009)

Wenn du A nicht erweitern kannst, und es keine solchen Methoden liefert, kannst
du mit diesen private Membern in B nix machen. Also das weiss ich definitiv 

...das suckt grad so, ich hasse sowas. Ich komm mir vor wie am ersten Tag Java.
Wie kann das sein, dass die nicht vererbt werden.... Wiiiildcard, Electroooonix, Aaaandre,.. ^^


----------



## diggaa1984 (30. Mrz 2009)

vielleicht sollte man dann langsam nachfragen warum du genau was ändern willst 

der Ersteller von A hatte dann entweder nicht alles bedacht, oder eben gerade doch :bahnhof:


----------



## hdi (30. Mrz 2009)

So, ich hab's:
Hier scheint es ganz einfach nur eine schwammige Terminologie zu geben.
"Erben" im streng objektorientierten Sinn heisst, dass das gererbte in der erbenden
Klasse sichtbar ist.
Was es nicht ist, daher die Ausrufe "private Member werden nicht vererbt".

Man kann aber Vererbung auch so definieren:
Alles, was zum einem erbenden Objekt gehört, und von der Superklasse stammt, 
wurde geerbt.

D.h. also private Member werden eben DOCH "vererbt". *Es gibt sie* in der Unterklasse,
aber sie sind nicht sichtbar.

So, *aber:* private Methoden werden wirklich nie, also wirklich gar nie, vererbt.
(Egal nach welcher Definition).
Eine private Methode existiert in der Unterklasse nicht, man kann sowas also zB auch nicht
überschreiben.

So... jetz kann ich schlafen gehen 

@Threadersteller:
Sry für die Verwirrung. Es ist so, wie ich grad sagte. Haste keine Methode in A definiert,
die in B sichtbar ist, hast du *null* Chancen, dieses private Member zu lesen oder schreiben.


----------



## diggaa1984 (30. Mrz 2009)

> Weil das nicht der Fall ist, müsste ja dann quasi jeder BMW intern ein eigenes Auto-Objekt
> mitschleppen?!



wie wärs mit .. BMW baut nur die Karosserie drum


----------



## hdi (30. Mrz 2009)

> wie wärs mit .. BMW baut nur die Karosserie drum


hahaha, mach dich halt drüber lustig  Das hat mich grad echt voll geschockt.
Und das alles nur weil die Definition von Vererbung nicht klar ist.

Das is genauso ein Kack wie mit "lokalen" Variablen. Was is eine lokale Variable, 
was is eine automatic variable, und es gibt noch 3 andere Ausdrücke, die jeder
anders interpretiert...

edit:
Weil auch noch protected erwähnt wurde: Ist okay soweit, aber man sollte wissen
dass eine Klasse, die ein protected Member erbt, dessen access modifier intern auf
private umschreibt.
In einer Subklasse der Subklasse wäre diese Variable also _nicht_ sichtbar, auch 
wenn sie in der Oberklasse protected deklariert wurde.

edit2: Ich hoffe ihr nehmt mir solche "Zusatz"-Infos über die nächsten Monate nicht so übel.
Es schadet ja nicht, aber der Zweck ist für mich quasi das einmal hinzuschreiben, für mich selber.
Weil ich grad für so ne Zertifiakt-Prüfung diesen fetten Study Guide büffel, und dort
lauter so Mist lesen muss, den ich mir auch noch merken muss 
Diese Sache mit protected wusste ich zB bis vor 2 Tagen gar nicht.
Und hier krieg ich die Chance von euch korrigiert zu werden, damit ich mir das nich
total falsch einpräg


----------



## Marco13 (30. Mrz 2009)

hdi hat gesagt.:


> Es ist so, wie ich grad sagte. Haste keine Methode in A definiert,
> die in B sichtbar ist, hast du *null* Chancen, dieses private Member zu lesen oder schreiben.



Und wir wissen ja: Pauschale Aussagen sind IMMER falsch  Mit Reflection kommt man da afaik ran. Ist aber nicht Sinn des ganzen...


----------



## berliner (30. Mrz 2009)

Darf ich ganz dreist nachfragen, ob Du mir an meinem oberen Beispiel zeigen kannst, wie das mit Reflection geht?


----------



## hdi (30. Mrz 2009)

Würd mich auch interessieren. _Wenn_ das geht, dann ist ja das private Keyword irgendwo unsinnig?


----------



## Ebenius (30. Mrz 2009)

hdi hat gesagt.:


> Würd mich auch interessieren. _Wenn_ das geht, dann ist ja das private Keyword irgendwo unsinnig?


Es geht und das _private_-Schlüsselwort ist nicht unsinnig. Sichtbarkeitseinschränkung hat nichts mit einem Sicherheitskonzept zu tun.



berliner hat gesagt.:


> Darf ich ganz dreist nachfragen, ob Du mir an meinem oberen Beispiel zeigen kannst, wie das mit Reflection geht?


Bitteschön. *[SIZE="+1"]Aber das ist nicht der Weg den Du gehen möchtest![/SIZE]*
[HIGHLIGHT="Java"]public class B extends AA {

  public String getX() {
    try {
      final Field field = AA.class.getDeclaredField("_X");
      field.setAccessible(true);
      return (String) field.get(this);
    } catch (SecurityException ex) {
      ex.printStackTrace();
    } catch (NoSuchFieldException ex) {
      ex.printStackTrace();
    } catch (IllegalArgumentException ex) {
      ex.printStackTrace();
    } catch (IllegalAccessException ex) {
      ex.printStackTrace();
    }
    return null;
  }
}[/HIGHLIGHT]
Ebenius


----------



## hdi (30. Mrz 2009)

> Sichtbarkeitseinschränkung hat nichts mit einem Sicherheitskonzept zu tun.


Ach? Also nur mit Kapselung? Krasse Sache, ist ja mal madig dass man mir die Variablen
aller Klassen aus jeder beliebigen Stelle im Programm rausziehen kann..

Was wäre denn dann ein Sicherheitskonzept gegen sowas? Wie kann man sich vor sowas
schützen?

Ich meine wenn ich mich in eine Stelle im Programm reinkriege, sagen wir bei einer
Bank-Software.

Ich bin nun in der Klasse Kunde, sehe dort eine Referenz auf Konto.
Der Setter verlangt eine PIN, per Reflection und den Namen des Setters weiss ich
aber sowohl wie die Klasse heisst als auch wie die Variable heisst (gehen wir davon
aus das ist Java-Beans konform).

Jetzt pack ich mir den Wert per Reflection und addiere da 15 Millionen drauf.

Bravo, Setter, du störst mich nicht. Ich dachte schon, dass es bei Settern und Gettern
auch darum geht,
durch eine Kontrollstelle hindurchgehen zu müssen... Das hat doch definitiv was mit 
Sicherheit zu tun?


----------



## Marco13 (30. Mrz 2009)

Nicht so ganz. "private" ist keine Firewall, sondern nur ein Hinweis zur richtigen Verwendung. In diesem Sinne ist das hier also falsch
[HIGHLIGHT="Java"]
import java.lang.reflect.*;

class A
{
    private int a = 123;

    public String toString()
    {
        return "a="+a;
    }
}


class B extends A
{
    public void doit() throws Exception
    {
        Field f = A.class.getDeclaredField("a");
        f.setAccessible(true);
        int a = f.getInt(this);
        System.out.println("In B#doit: a="+a);
        f.setInt(this, 456);
    }
}


class PrivateAccessTest
{
    public static void main(String args[]) throws Exception
    {
        B b = new B();
        b.doit();
        System.out.println("After B#doit: "+b);
    }
}
[/HIGHLIGHT]


----------



## hdi (30. Mrz 2009)

Ok, also access modifier sind nur eine für den Programmierer aufgezogene Struktur?
Damit ich selber (oder ein anderer Programmierer) zB nicht den Radius eines Kreises
per k.radius = -10 setzen darf,
sondern der Setter das abfängt?
Und aber der Programmierer ja sehr wohl weiss, dass er es NICHT über Reflection machen
sollte, auch wenn er kann,
weil er damit sowohl sich als auch die Kollegen "hintergeht", und sich selber Gefahren
ins Programm schiebt?

Ok also das hab ich wohl verstanden, habe wohl nur die Wirkung von sowas überschätzt.


----------



## Schandro (30. Mrz 2009)

> So, *aber:* private Methoden werden wirklich nie, also wirklich gar nie, vererbt.
> (Egal nach welcher Definition).
> Eine private Methode existiert in der Unterklasse nicht, man kann sowas also zB auch nicht
> überschreiben.


Natürlich existiert während der Laufzeit der Bytecode, der für die private Methode des Objects steht. Ansonsten könnten public Methoden der Oberklasse ja nicht ihre internen private Methoden aufrufen...
Und per Reflection könnte man deswegen auch auf diese private Methoden zugreifen !??


----------



## hdi (30. Mrz 2009)

Schandro, recht herzlichen Dank.. Jetz bin ich wieder verwirrt 
Du hast natürlich Recht...Boah.. diese Definitionen.

Wie ist das nun? Kann man private Variablen so behandeln wie private Methoden?
Oder gibt es dann in der Subklasse doch irgendeinen Unterschied?

Ich hab gelesen man kann private Methoden in der Subklasse weder überschreiben
noch überladen, weil es sie dort schlichtweg nicht gibt, also innerhalb des Subklassen-"Scopes",
sagen wir mal so..

Und privat geerbte Variablen.. was ist damit? Kann man die überschatten?

Wenn nein, dann gibt es doch keinen Unterschied zwischen Vererbung von privaten
Variablen und privaten Methoden, oder?
Beide "sind da", aber beide werden nicht "vererbt" im OO-Sinne und können in der Subklasse
nicht geändert, überladen oder überschattet werden.

Ist das richtig?


----------



## Ebenius (30. Mrz 2009)

"Überschatten" ist da das falsche Wort. Von "überschatten" oder "verstecken" oder "verdecken" spricht man, wenn eine Variable namens _N_ in einer Ableitung benutzt wird und in einer darüberliegenden Klasse eine aus der Ableitung sichtbare Variable mit selbem Namen _N_ versteckt wird. Man kann dann nicht mehr so einfach auf die darüber liegende Variable _N_ zugreifen, weshalb von "verstecken" oder "überschatten" die Rede ist.

Wenn ich mich nicht irre, nennt man das genauso, wenn man eine lokale Variable so benennt und eine Variable der Instanz damit versteckt. Und auch wenn man in einer Inner Class Variablennamen benutzt die's draußen gibt. Aber das tut in diesem Kontext nix zur Sache.

Variablen können natürlich verdeckt werden, wenn sie sichtbar sind.

Private Methoden und private Variablen sind in einer Ableitung ohnehin unsichtbar und werden daher auch nicht überdeckt.

Alles existiert immer und wird auch vererbt. Nur sichtbar ist es eben nicht immer.

Ich hoffe, ich konnte zu Deiner Verwirrung beitragen. 

Ebenius


----------



## hdi (30. Mrz 2009)

Ja genau, also beides ist da, nix ist sichtbar, daher kann man Methoden nicht
- überladen
- überschreiben
und Variablen nicht
- überschatten

wenn sie private geerbt wurden (oder korrekt gesagt: eben nicht geerbt wurden )


----------



## Ebenius (30. Mrz 2009)

Inhaltlich richtig, aber ich halte diese Formulierung für fehlerhaft. Die Eigenschaften und Methoden sind eventuell nicht sichtbar, werden aber trotzdem vererbt.

Ebenius


----------



## hdi (30. Mrz 2009)

Wie angesprochen: Diese Definition scheint nicht eindeutig zu sein.
Wenn du googlest findest du genug - auch professionelle Quellen - die sagen
dass sowas "never inherited" wird. Die verstehen eben unter Vererbung, dass das
Zeug auch sichtbar ist in der Unterklasse.

Ich persönlich ziehe es aber auch vor, zu sagen etwas wird vererbt, wenn es nun mal
in der Unterklasse exisitiert (wenn auch nicht sichtbar ist)

Für die SCJP Prüfung merke ich mir das aber anders, denn die sehen das eben so,
dass es NICHT vererbt wird.


----------



## Wildcard (30. Mrz 2009)

hdi hat gesagt.:


> Was wäre denn dann ein Sicherheitskonzept gegen sowas? Wie kann man sich vor sowas
> schützen?


Der SecurityManager entscheidet ob es erlaubt ist auf private Felder zuzugreifen, denn im Gegensatz zur Sichtbarkeit ist der SecurityManager ein Sicherheitskonzept


----------

