OOP This-Referenzs > wo liegt mein Denkfehler?

innocent

Mitglied
Hey!

Arbeite mich für die Uni nach und nach in Java ein. Momentan bin ich bei der fleißigen Lektüre der Insel. Nebenbei muss ich in einer Gruppe ein Kartenspiel in Java implementieren.

Jetzt habe ich eine Methode Push(object,ip) geschrieben, mit welcher man Objekte über eine Socketverbindung schieben kann. Nun ließt man, dass es immer schlecht sei, Objekte als Parameter zu übergeben, da das prozedurale Programmierung sei.

Gut, ursprünglich wollte ich die Push()-Methode an Objekte vererben. Dabei bin ich auf ein Problem mit der This-Referenz gestoßen.


Hier ein Programm, welches mein Problem verdeutlichen soll: Prozedural:
Java:
class Mutter {
	String Variable = "Elternelement > Mutter";
	public void Push() {
		
	}
	public void Push(Sohn asd) {
		System.out.println(asd.Variable);
	}
	public void Push(Mutter asd) {
		System.out.println(asd.Variable);
	}
}

class Sohn extends Mutter {
	String Variable = "Kindelement > Sohn";
}

public class ThisReferenz {
	public static void main(String[] args) {
		Sohn sohn = new Sohn();
		Mutter mutter = new Mutter();
		System.out.println("laeuft");
		System.out.println("Sohn.Push()");	
		sohn.Push(sohn);
		System.out.println("Mutter.Push()");
		mutter.Push(mutter);
	}
}
Der "Fehler" im Programm: Ich muss das Objekt, welches ich auf der Konsole ausgeben will, übergeben. Aber es funktioniert.

OOP:
Java:
class Eltern {
	private String Variable = "Elternelement > Mutter";
	public void Push() {
		System.out.println(this.Variable);
	}
}

class Kind extends Eltern {
	private String Variable = "Kindelement > Sohn";
}

public class ThisReferenz2 {
	public static void main(String[] args) {
		Kind sohn = new Kind();
		Eltern mutter = new Eltern();
		System.out.println("Laeuft");
		System.out.println("sohn.Push()");	
		sohn.Push();
		System.out.println("mutter.Push()");
		mutter.Push();
	}
}
Ausgabe:
Code:
Laeuft
sohn.Push()
Elternelement > Mutter
mutter.Push()
Elternelement > Mutter




Die Push()-Methode steht hier als Synonym für meine Netzwerkmethode. Habe ich einen Fehler, oder überschreibt die Eltern-Variable die des Kindes?
Ich dachte, nur die Methode wird vererbt und würde dann über this auf die Variable des Kindes zugreifen. Dem scheint nicht so zu sein.
 
Variablen werden nicht vererbt... Du kannst das ganze aber über Getter- und/oder Setter-Methoden lösen.
Des Weiteren sollten Methoden Camel Case mit beginnendem Kleinbuchstaben geschrieben werden, in deinem Fall also [c]push()[/c].
 
Also der Moment in dem einen da Licht aufgegangen ist, was du meintest war echt schön 😉
(Soll jetzt nicht heißen das du dich schlecht ausgedrückt hast oder so, ich liege gerade Krank im Bett und bin nicht ganz mit allen grauen Zellen dabei)

Also da die variable private gesetzt ist dürfte sie ja schonmal nicht die des Kindes überdecken, da sie ja im Kind garnicht exziestiert. Wobei sich die Ausgabe ja glaube ich nicht ändert, wenn du das private wegmachen wirst.

Ich würde jetzt sagen das das push vom Kind halt über den this Zeiger immernoch auf die Eltern zeigt, quasi als hättest du Eltern.variable im system.out.


Jedoch kann ich da auch nur mutmaßen wieso sich der this-Zeiger da so verhällt und bin mal auf die antwort von jemanden gespannt der sich da auskennt.
 
Zuletzt bearbeitet:
Variablen- und Methodennamen schreibt man in Java klein.

In Sohn hast du eine neue Variable "Variable", die die mütterliche gewissermaßen "überdeckt". Das hier sollte funktionieren:

Java:
class Sohn extends Mutter {
    public Sohn() {
       Variable = "Kindelement > Sohn";
    }
}

Damit überschreibst du die vorhandene Variable und erzeugst keine neue.
 
Variablen werden nicht vererbt... Du kannst das ganze aber über Getter- und/oder Setter-Methoden lösen.
Des Weiteren sollten Methoden Camel Case mit beginnendem Kleinbuchstaben geschrieben werden, in deinem Fall also [c]push()[/c].

Danke, kleine Methodennamen, werde ich mir merken.

Hier geht's jetzt aber nicht um die Variablen. Das Ganze soll nur ein Beispiel für mein Netzwerkproblem sein. Dort habe ich verschiedene Objekte, die ich mittels objectreferenz.push() auf den Server schieben will.

Das funktioniert hier ja leider nicht, da die dazu benötigte This-Referenz auch beim Kind-Objekt die Mutter-Variable ausgibt.

Variablen- und Methodennamen schreibt man in Java klein.

In Sohn hast du eine neue Variable "Variable", die die mütterliche gewissermaßen "überdeckt". Das hier sollte funktionieren:

Java:
class Sohn extends Mutter {
    public Sohn() {
       Variable = "Kindelement > Sohn";
    }
}

Damit überschreibst du die vorhandene Variable und erzeugst keine neue.

Werde ich gleich testen! Aber wenn ich das überschreibe, kann ich dann noch auf die Muttervariable zugreifen, wenn ich ein Mutterobjekt benutze? Spirch: mutterobjekt.push()?

wer sagt den sowas?

Steht im "Java ist auch eine Insel"-Buch.
 
@ARadauer

das sagt doch jeder,
man muss es nur richtig lesen

> Person p = ..;
> String name = p.getName();
ist in aller Regel besser als
> Person p = ..;
> String name = PersonMethoden.getName(p);

dass damit sämliche Parameter verboten sind, ist nur eine falsche Folgerung
 
Natürlich sind Variablen der Elternklasse (sofern nicht private) auch in der Kindklasse sichtbar. Dass man einfach eine gleichnamige Variable in der Kindklasse "drüberdefinieren" darf, ohne Warnung und so, ist schon ziemlich starker Tobak. Da kein halbwegs erfahrener Java-Programmierer überhaupt auf so eine Idee kommen würde, ist die allgemeine Konfusion vorprogrammiert :-D
 
[Java]
public class Eltern {
String s = "alt";

public void printString() {
System.out.println(s);
}
public class Kind extends Eltern{
String s = "jung";
}
[/Java]
e.printString(); //alt
k.printString(); //alt
________________________________________
[Java]
public class Eltern {
String s = "alt";

public void printString() {
System.out.println(s);
}
public class Kind extends Eltern{
String s = "jung";

public Kind() {
s = "jung2";
super.s = "jung3";
}
}
[/Java]
e.printString(); //alt
k.printString(); //jung3
e.printString(); //alt <- - sind ja andere Objekte
_________________________________________
[Java]
public class Eltern {
String s = "alt";

public void printString() {
System.out.println(s);
}
public class Kind extends Eltern{
public Kind() {
s = "jung";
}
}
[/Java]
e.printString(); //alt
k.printString(); //jung
__________________________
[Java]
public class Eltern {
String s = "alt";

public void printString() {
System.out.println(s);
}
public class Kind extends Eltern{
String s = "jung";

public void printString() {
System.out.println(s);
}
}
[/Java]
e.printString(); //alt
k.printString(); //jung

So wie der letzt Fall aussieht war wohl die Idee von "innocent", das das Kind die Methode zur Stringausgabe erbt und somit einen eigenen String names s ausgeben kann. Jedoch scheint die Vererbung dort etwas anderes zu funktionieren wie man es intuitiv erwarte würde, denn die geerbte Methode im Kind schafft es sogar auf eine Variable zuzugreifen die private ist, also normal garnicht im Kind sichtbar ist. somit bleibt eigentlich keine andere möglichkeit, das aus dem this.varibale in der Klasse Kind ein super.variable geworden ist.

ich fand es jetzt mal ganz interessant sich einige Fällte zu überlegen und nachzuvollziehen wieso es in welchem Fall zu welcher testausgabe kam.

mfg neon
 
ps: innocent, nutz doch nächstesmal die Forensuche 😛

nein, spaß bei Seite, ich finde das einen recht interessanten Post von dir, weil dein Gedankengang mit dem this-Zeiger zumindest für mich garnicht so abwegig ist.
 
Zuletzt bearbeitet:
Hmm. Gut, die Variablen habe ich als Privat geklariert.

Ich hatte mir das so vorgestellt, dass die Push()-Methode an das Kind vererbt wird. Greife ich nun über eine Objektreferenz des Kindelements auf die geerbte Methode zu, müsste this doch die Objekt-Variable des Kindelements übergeben, oder nicht?


Noch mal gesagt:
Das hier ist nur als Beispiel gedacht. Ich möchte eine wesentlich komplexere Push()-Methode an die Netzwerkpakete vererben. Aber damit die funktioniert muss ich auf die jeweiligen Netzwerkpakete mit This zugreifen.


ps: innocent, nutz doch nächstesmal die Forensuche 😛

Haha ^^
Ich bin generell erst über diverse Suchen im Internet auf dieses Forum gestoßen.
 
Zuletzt bearbeitet:
Ich hatte den String in Eltern bewusst nicht private gesetzt, da er somit ja nicht in Kind sichtbare wäre, und die "Verwirrung" ja nur halb so groß wäre.

Das this wird ja scheinbar durch einen Zeiger auf die Superklasse Eltern. Also musst du dich jetzt wohl von der Methode trennen und wie bereits einer meiner Vorredner schon gemeint hat auf getter und setter Methoden zurückgreifen.
 
Wozu Getter und Setter, wenn ich mit push() auf das aufgerufene Objekt über das Netzwerk schicken will?

Wie gesagt, das hier ist nur ein Beispiel, ich verstehe nicht, warum es nicht funktioniert. Ich dachte This gibt immer die Referenz auf das aktuelle Objekt zurück und nicht eine Referenz auf das Superobjekt.
 
Und warum funktioniert es dann in meinem Beispiel nicht? Wo liegt da der Fehler? Wie gesagt, es geht nicht darum, die Strings auszugeben, das ist nur ein Synonym für eine komplexere Methode die eine Objekt-Referenz erwartet und über das Netzwerk verschickt.
 
Und warum funktioniert es dann in meinem Beispiel nicht? Wo liegt da der Fehler?
Wurde doch lang & breit diskutiert, warum private membervariablen statisch gebunden werden und nicht dynamisch.

Public/protected/package protected bzw. getter wären die Lösung.
 
this referenziert zwar auf das Kindobjekt, die aufgerufene Methode push() ist aber in der Superklasse implementiert und kennt nur deren Variable Variable, sie weiss garnichts von einer gleichnamigen Variable in der Subklasse (Sie weiss ja noch nicht mal, dass es eine Subklasse gibt/geben könnte).
Da Variablen - wie des Öfteren erwähnt - nicht vererbt werden, kann man sie auch nicht überschreiben. Es handelt sich also um zwei verschiedene Variablen.

Mögliche Vorgehensweisen: die Variable in der Superklasse protected machen und in der Subklasse deren Inhalt überschreiben oder per setMethode von aussen zugänglich machen.
 
..
Da Variablen - wie des Öfteren erwähnt - nicht vererbt werden, kann man sie auch nicht überschreiben. ..
Sorry, aber das stimmt so nicht.

Variablen werden immer vererbt, aber deswegen sind sie nicht sichtbar.
Wenn der Compiler eine private Variable findet, dann linkt er sie statisch, gibt ja keinen Grund für dynamisches Linken zur Laufzeit, und das ist das Problem hier.
 
So, noch etwas gelesen. Jetzt habe ich kapiert, worauf Ihr hinaus wolltet! Dankeschoen!

Java:
class Eltern {
	private String Variable;
	public void Push() {
		System.out.println(this.Variable);
	}
	public void set(String var) {
		this.Variable = var;
	}
}

class Kind extends Eltern {
	public String Variable;
}

public class ThisReferenz2 {
	public static void main(String[] args) {
		Kind sohn = new Kind();
		Eltern mutter = new Eltern();
		mutter.set("Mutterelement");
		sohn.set("Sohnelement");
		System.out.println("Laeuft");
		System.out.println("sohn.Push()");	
		sohn.Push();
		System.out.println("mutter.Push()");
		mutter.Push();
	}
}

Ausgabe:
Laeuft
sohn.Push()
Sohnelement
mutter.Push()
Mutterelement
 

Zurück
Oben