Compiler-Fehler vererbtes protected

keksi

Mitglied
Hallo Leute

Ich habe hier ein komisches Compiler-Problem, das ich jetzt auf zwei winzige Klassen herunterbrechen konnte:

Java:
package p1;
public class Class1
{
	protected static Class1 OnlyInstance;

	public static void go()
	{
		OnlyInstance = new Class1();
		OnlyInstance.doSomething();
	}

	protected void doSomething(){}
}

Java:
package p2;
import p1.Class1;
public class Class2 extends Class1
{
	public static void go()
	{
		OnlyInstance = new Class2();
		OnlyInstance.doSomething();
	}

	public static void go2()
	{
		new Class2().doSomething();
		((Class1)new Class2()).doSomething();
	}
}

Die Class2 kompiliert nicht - er meckert an 2 Stellen (Zeilen 8 und 14), dass die Methode doSomething() aus Class1 nicht sichtbar ist! Dabei ist Class2 eine Unterklasse von Class1 und müsste alle protected Methoden von Class1 sehen.

Es ist mir ein Rätsel. Kann jemand helfen?

Vielen Dank Leute
Keksi
 
Zuletzt bearbeitet von einem Moderator:
S

SlaterB

Gast
du befindest dich nicht direkt in einer normalen Methode von Class2, da gäbe es kein Problem,
ein statischer Kontext ist anscheinend bisschen was anderes, kannte ich auch noch nicht so genau

wenn du eine Class2-Variable nimmst, kannst du von static aus protected und private der eigenen Klassen nutzen und auch endlich protected der super-Klasse,
aber für eine Class1-Variable nicht,

tja, mehr als diese Feststellung kann ich gar nicht beitragen, Workaround sind nichtstatische Methoden-Varianten,
groß erklären kann ich es nicht
 
Zuletzt bearbeitet von einem Moderator:

Plopo

Bekanntes Mitglied
Folgendes funktioniert bei mir

Java:
package p2;

import p1.Class1;

public class Class2 extends Class1
{
  public static void go ()
  {
    onlyInstance = new Class2 ();
    ((Class2) onlyInstance).doSomething ();
  }

  public static void go2 ()
  {
    new Class2 ().doSomething ();
    (new Class2 ()).doSomething ();
  }
}
 

keksi

Mitglied
Hallo slaterB.

Vielen Dank für Deine superschnelle Antwort!

Wenn die Methode go() nicht statisch ist, ist es leider genau so. Es liegt also nicht am statischen Kontext.

Die statische Variable OnlyInstance in die Klasse Class2 zu kopieren ist keine Option, da diese Variable in Class1 verwendet wird und an Class2 vererbt werden soll.

Gruss
Keksi
 
S

SlaterB

Gast
in der Tat, das erschüttert mich noch etwas mehr,

um auch ein wenig konstruktives beizutragen eine weitere Verkürzung der Sache:

Java:
public class Class1
{
    protected void doSomething(){}
}


-----

public class Class2 extends Class1
{
    public Class2()
    {
        doSomething(); // geht

        Class1 c1 = this;
        c1.doSomething(); // geht nicht
    }
}

liegen beide Klassen in demselben package geht auch der zweite Aufruf, bei verschiedenen nicht mehr,
da darf ich wohl einen Erklärungsversuch wagen:
es wird für Class1 dessen Sicht nach außen in andere packages verwendet,
unabhängig davon dass Class2 zufällig ein Erbe ist, auch statisch oder nicht dann irrelevant, entgegen meiner vorherigen Behauptung
 

keksi

Mitglied
Hallo Plopo

Folgendes funktioniert bei mir

Java:
package p2;

import p1.Class1;

public class Class2 extends Class1
{
  public static void go ()
  {
    onlyInstance = new Class2 ();
    ((Class2) onlyInstance).doSomething ();
  }

  public static void go2 ()
  {
    new Class2 ().doSomething ();
    (new Class2 ()).doSomething ();
  }
}

Krass. Wenn ich Class1 auf Class2 caste, dann klappts. Unlogischer gehts nicht.

???:L
Keksi
 

keksi

Mitglied
in der Tat, das erschüttert mich noch etwas mehr,

um auch ein wenig konstruktives beizutragen eine weitere Verkürzung der Sache:

Java:
public class Class1
{
    protected void doSomething(){}
}


-----

public class Class2 extends Class1
{
    public Class2()
    {
        doSomething(); // geht

        Class1 c1 = this;
        c1.doSomething(); // geht nicht
    }
}

liegen beide Klassen in demselben package geht auch der zweite Aufruf, bei verschiedenen nicht mehr,
da darf ich wohl einen Erklärungsversuch wagen:
es wird für Class1 dessen Sicht nach außen in andere packages verwendet,
unabhängig davon dass Class2 zufällig ein Erbe ist, auch statisch oder nicht dann irrelevant, entgegen meiner vorherigen Behauptung

Scheint so. Dadurch ist "protected" für die Katz. Denn dies wäre eben für die Erben gedacht.

Keksi
 
P

pappawinni

Gast
protected
- Elemente des Typs protected sind in der Klasse selbst und in abgeleiteten Klassen sichtbar. Für Aufrufer von Objekten der Klasse (Instanzen) sind protected-Variablen und -Methoden nur dann verwendbar, wenn sie in dem selben Paket definiert wurden.
- protected-Elemente sind vor Zugriffen von außen geschützt, können aber von abgeleiteten Klassen verwendet werden.
- Werden Variablen und Methoden ohne eines der drei Attribute private, protected oder public definiert, so entspricht ihr Verhalten im wesentlichen dem von Elementen des Typs protected.

[EDIT]
hab ich von hier:
Java - protected - VirtualUniversity
[/EDIT]
 
Zuletzt bearbeitet von einem Moderator:

Jodo

Aktives Mitglied
Krass. Wenn ich Class1 auf Class2 caste, dann klappts. Unlogischer gehts nicht.

???:L
Keksi

Wieso unlogisch? Du hast nach dem cast ein Objekt desselben Typs deiner eigenen Klasse und die sollte man ja schon aufrufen können.

Bei deinem ersten Beispiel versuchst du auf die protected-Methode der Class1 zuzugreifen obwohl Class2 in einem anderen package liegt. Protected heisst ja aber, dass die Methode nur innerhalb des packages und den Unterklassen sichtbar ist. Aber nur weil es eine Unterklasse ist, heißt das nicht, dass du die Methode der Superklasse, die in einem anderen package liegt, aufrufen kannst. Man würde ja dann von außerhalb des packages die Möglichkeit haben den Zustand einer Instanz der Superklasse zu ändern, obwohl diese das nicht explizit erlaubt.

Bei einer protected Klassenvariable wird es deutlicher. Sonst wäre folgendes möglich:
Code:
package p1;

public class Class1
{
    protected Class1 onlyInstance;
}
Code:
package p2;
import p1.Class1;

public class Class2 extends Class1
{
	public Class1 getOI(Class1 c1) {
		return c1.onlyInstance;
	}
}

D.h. wenn du auf protected Member der Superklasse aus einem anderen package zugreifen könntest würde das protected aushebeln und überflüssig machen.
 
Zuletzt bearbeitet:

Noctarius

Top Contributor
- Werden Variablen und Methoden ohne eines der drei Attribute private, protected oder public definiert, so entspricht ihr Verhalten im wesentlichen dem von Elementen des Typs protected.

Das kann ich allerdings so nicht ganz stehen lassen. Wird kein expliziter Visibility-Modifier benutzt so gilt bei implementierten Methoden die Default-Visibility und die besagt, dass die Methode innerhalb des selben Packages aufrufbar ist. Quasi public für Klassen innerhalb des selben Packages, private für Klassen außerhalb. Wird auch Package-Private oder Friend-Visible bezeichnet.
 

keksi

Mitglied
Wieso unlogisch? Du hast nach dem cast ein Objekt desselben Typs deiner eigenen Klasse und die sollte man ja schon aufrufen können.

Bei deinem ersten Beispiel versuchst du auf die protected-Methode der Class1 zuzugreifen obwohl Class2 in einem anderen package liegt. Protected heisst ja aber, dass die Methode nur innerhalb des packages und den Unterklassen sichtbar ist.

Was Du schreibst stimmt nicht. Eine Klasse kann auf protected members zugreifen, wenn die betreffende Klasse im selben Package liegt ODER eine Unterklasse ist. Nicht UND, sondern ODER. Ansonsten wäre die Einschränkung "protected" 100% identisch mit der Einschränkung "(leer)" = package.

Zitat aus "Java ist auch eine Insel 10": protected-Eigenschaften werden an alle Unterklassen vererbt.

Der Beweis liegt auch in dem Code, den ich mitgegeben habe:

Code:
package p2;
import p1.Class1;
public class Class2 extends Class1
{
    public static void go2()
    {
        new Class2().doSomething();
    }
}

Das würde nicht kompilieren, wenn Du Recht hättest.

Aber nur weil es eine Unterklasse ist, heißt das nicht, dass du die Methode der Superklasse, die in einem anderen package liegt, aufrufen kannst. Man würde ja dann von außerhalb des packages die Möglichkeit haben den Zustand einer Instanz der Superklasse zu ändern, obwohl diese das nicht explizit erlaubt.

D.h. wenn du auf protected Member der Superklasse aus einem anderen package zugreifen könntest würde das protected aushebeln und überflüssig machen.

Das ist doch genau der Zweck von protected Methoden: DIESE dürfen von Unterklassen aufgerufen werden. private Methoden natürlich nicht. Deshalb kann man auch zwischen private und protected unterscheiden.

Was völlig unlogisch ist, ist nur diese Zeile:

Code:
package p2;
import p1.Class1;
public class Class2 extends Class1
{
    public static void go2()
    {
        ((Class1)new Class2()).doSomething();
    }

Wenn ich die Instanz der Unterklasse Class2 (welche die Methode doSomething() KENNT, s.o.) auf die Oberklasse caste, dann kennt die Klasse Class1 die eigene Methode nicht mehr!

Keksi
 
P

pappawinni

Gast
Das kann ich allerdings so nicht ganz stehen lassen. Wird kein expliziter Visibility-Modifier benutzt so gilt bei implementierten Methoden die Default-Visibility und die besagt, dass die Methode innerhalb des selben Packages aufrufbar ist. Quasi public für Klassen innerhalb des selben Packages, private für Klassen außerhalb. Wird auch Package-Private oder Friend-Visible bezeichnet.

Aha, und wo ist dann da der WESENTLICHE Unterschied im Verhalten? Den hab ich da jetzt nicht wirklich raus gelesen.
 

Noctarius

Top Contributor
protected = gleiches Packages ODER Subclass (und die kann in anderen Packages sein)
default = gleiches Package aber KEINE Subclasses in anderen Packages

Wenn das für dich das Selbe ist, dann ist es sicher auch das Gleiche, oder? :)
 

hexx

Mitglied
Was Du schreibst stimmt nicht. Eine Klasse kann auf protected members zugreifen, wenn die betreffende Klasse im selben Package liegt ODER eine Unterklasse ist. Nicht UND, sondern ODER. Ansonsten wäre die Einschränkung "protected" 100% identisch mit der Einschränkung "(leer)" = package.

Java Language Specification

  • Innerhalb einer Unterklasse, kann man auf die ererbten protected Elemente (Zur Verdeutlichung: Zugriff mit super.* möglich) der Oberklasse zugreifen, egal in welchem Paket die Unterklasse liegt.
  • Von außen (über eine Variable vom Typ der Oberklasse) kann man nur innerhalb des Pakets auf die protected Elemente zugreifen. Auch wenn die Variable innerhalb der Unterklasse deklariert ist.
 
S

SlaterB

Gast
Was Du schreibst stimmt nicht. Eine Klasse kann auf protected members zugreifen, wenn die betreffende Klasse im selben Package liegt ODER eine Unterklasse ist. Nicht UND, sondern ODER.
wenn man schreibt oder sagt, dass man 'morgens und abends zu Hause erreichbar ist' dann meint man auch ein logisches ODER von zwei Zeiträumen, nicht beide Bedingungen gleichzeitig..

nicht die Sprache überinterpretieren ;)
 
P

pappawinni

Gast
protected = gleiches Packages ODER Subclass (und die kann in anderen Packages sein)
default = gleiches Package aber KEINE Subclasses in anderen Packages

Wenn das für dich das Selbe ist, dann ist es sicher auch das Gleiche, oder? :)

Ich hab ja nicht gesagt, dass das für mich das gleiche oder gar das selbe wär.
Aber ich seh nicht, was es für mich für einen Unterschied macht, wenn ich ne Unterklasse zwar definieren kann, aber dann doch nichts erbe, dann kann ich es auch gleich lassen, oder ?

/pappawinni<< Java-Anfänger
 

Jodo

Aktives Mitglied
Der Beweis liegt auch in dem Code, den ich mitgegeben habe:

Code:
package p2;
import p1.Class1;
public class Class2 extends Class1
{
    public static void go2()
    {
        new Class2().doSomething();
    }
}

Das würde nicht kompilieren, wenn Du Recht hättest.
Der Code kompiliert, weil du
Code:
doSomething()
innerhalb der Klasse Class2 auf einem (anonymen) Objekt des Typs Class2 aufrufst. Ein Class2-Objekt kennt natürlich die doSomething()-Methode weil es sie erbt.
Das von mir gepostete Code-Beispiel kompiliert nicht, weil versucht wird in Class2 die protected Variable auf einem Class1-Objekt aufzurufen. Trotzdessen, dass dies die Superklasse ist, funktioniert es aus genanntem Grund nicht.

Das ist doch genau der Zweck von protected Methoden: DIESE dürfen von Unterklassen aufgerufen werden. private Methoden natürlich nicht. Deshalb kann man auch zwischen private und protected unterscheiden.

Was völlig unlogisch ist, ist nur diese Zeile:

Code:
package p2;
import p1.Class1;
public class Class2 extends Class1
{
    public static void go2()
    {
        ((Class1)new Class2()).doSomething();
    }

Wenn ich die Instanz der Unterklasse Class2 (welche die Methode doSomething() KENNT, s.o.) auf die Oberklasse caste, dann kennt die Klasse Class1 die eigene Methode nicht mehr!
Das ist doch wieder genau das gleiche. Hier versucht du wieder in der Klasse Class2, auf einem Objekt des Typs Class1 die Methode doSomething() aufzurufen. Mit
Code:
super.doSomething()
geht es.

Nicht die Klasse Class1 kennt die eigene Methode nicht mehr, sondern Class2 sieht die Methode auf dem Class1-Objekt nicht weil Class1 in einem anderen package definiert ist.
Sonst wäre es wie gesagt möglich den Zustand eines anderen Objektes zu beeinflussen sobald dieses Variablen mit dem modifier protected besitzt und man eine Unterklasse ableitet. Und eben noch schlimmer, man könnte dessen Sichtbarkeit auf public ändern, wie in meinem Code-Beispiel gezeigt.
 
Zuletzt bearbeitet:
P

pappawinni

Gast
Summa summarum..

private: kein Zugriff von anderen Klassen; wird nicht geerbt

default (package): Zugriff von Klassen im selben Package, nicht von Klassen außerhalb; wird von Klassen im selben Package geerbt, von Klassen in anderen Packages nicht

protected: Zugriff von Klassen im selben Package, nicht von Klassen außerhalb; wird geerbt

public: Zugriff von allen anderen Klassen; wird geerbt

Wenn ich das richtig verstehe, dann erbt man bei protectet zwar auch außerhalb, kann aber nicht zugreifen.
Also ist das Verhalten im Wesentlichen wie bei default.
Intressant wäre dann zu wissen, wozu es nützt etwas zu erben, worauf man nicht zugreifen kann.
Ist das vielleicht so ne Art Java-ääätsch.. haha, das hättest du wohl gern .. nix da, musst du dir selber stricken?
 

Jodo

Aktives Mitglied
Kein wesentliches Verhalten wie bei default!

Natürlich kann eine Unterklasse, die außerhalb des packages liegt, auf Methoden/Felder des Superklasse zugreifen, aber nicht auf Methoden/Felder von Objekten der Superklasse.

Code:
package p1;
public class Class1
{
    protected Class1 onlyInstance;
    
    public void foo() {
    	onlyInstance.doSomething();
    }

	protected void doSomething(){}
}
Code:
package p2;
import p1.Class1;
public class Class2 extends Class1
{ 
    public void foo() {
    	super.doSomething(); 		        //geht
    	super.onlyInstance = new Class2();	//geht
    	this.doSomething();			//geht
    	this.onlyInstance = new Class2(); 	//geht
    	
    	
    	Class1 c1 = new Class1();
    	c1.doSomething();			//geht nicht -> compiler error
    	c1.onlyInstance = new Class2();		//geht nicht -> compiler error
    	
    	((Class2)c1).doSomething();		//geht, weil man ein Class2-Objekt hat
    	((Class2)c1).onlyInstance = new Class2();//geht, weil man ein Class2-Objekt hat
    	
    	Class2 c2 = new Class2();
    	c2.doSomething();			//geht
    	c2.onlyInstance = new Class2();		//geht
    	
    	((Class1)c2).doSomething();		//geht nicht, weil man ein Class1-Objekt hat -> compiler error
    	((Class1)c2).onlyInstance = new Class2();//geht nicht, weil man ein Class1-Objekt hat -> compiler error
    }
}
 
Zuletzt bearbeitet:

Marco13

Top Contributor
Ich habe nicht alles im Detail nachvollzogen (ist ja ganz schön was los hier ;) ) aber ... Wenn ich das richtig sehe, geht es um die Frage, ob die erbende Klasse auf die protected-Elemente "bezogen auf sich selbst" zugreifen kann oder nicht Auf die Methoden, die protected sind, und die sie selbst geerbt hat, und die damit "ihre eigenen" sind, kann sie zugreifen. Aber der allgemeine Zugriff auf protected-Methoden der Klasse, von der sie erbt, ist nicht möglich (außer, wenn sie im gleichen package liegt).

Zugegeben, in dieser Form hätte ich das auch nicht gewußt. Wenn sich der Staub hier gelegt hat ist das was für dien Java Quiz Thread :D
 

keksi

Mitglied
Code:
package p1;
public class Class1
{
    protected Class1 onlyInstance;
    
    public void foo() {
    	onlyInstance.doSomething();
    }

	protected void doSomething(){}
}
Code:
package p2;
import p1.Class1;
public class Class2 extends Class1
{ 
    public void foo() {
    	super.doSomething(); 		        //geht
    	super.onlyInstance = new Class2();	//geht
    	this.doSomething();			//geht
    	this.onlyInstance = new Class2(); 	//geht
    	
    	
    	Class1 c1 = new Class1();
    	c1.doSomething();			//geht nicht -> compiler error
    	c1.onlyInstance = new Class2();		//geht nicht -> compiler error
    	
    	((Class2)c1).doSomething();		//geht, weil man ein Class2-Objekt hat
    	((Class2)c1).onlyInstance = new Class2();//geht, weil man ein Class2-Objekt hat
    	
    	Class2 c2 = new Class2();
    	c2.doSomething();			//geht
    	c2.onlyInstance = new Class2();		//geht
    	
    	((Class1)c2).doSomething();		//geht nicht, weil man ein Class1-Objekt hat -> compiler error
    	((Class1)c2).onlyInstance = new Class2();//geht nicht, weil man ein Class1-Objekt hat -> compiler error
    }
}

Dieser Code ist eine ausgezeichnete Zusammenfassung - genau darum geht es!

Allein warum das so ist, kapiere ich nicht. In meinen Augen ist das ein Fehler des Compilers. Wenn "protected" bedeutet, dass Instanzen von Unterklassen auf die Methoden und Felder der Oberklasse zugreifen können (unabhängig vom Package der Ober- und Unterklassen), warum funktioniert das dann hier nicht?

Jodo, kannst Du mir Deine Erklärung mit dem anonymen Objekt genauer erklären? Was ist ein anonymes Objekt?

Natürlich kann eine Unterklasse, die außerhalb des packages liegt, auf Methoden/Felder des Superklasse zugreifen, aber nicht auf Methoden/Felder von Objekten der Superklasse.

Und das verstehe ich auch nicht. Natürlich geht es mir nur um die Methoden und Felder der Objekte und nicht die der Superklasse. Was sind Methoden und Felder der Klasse?

Danke
Keksi
 

Noctarius

Top Contributor
Der Compiler sieht einfach keinen Subclass Scope wenn es sich um Class1 handelt. [c]((Class2) c1).doSomething()[/c] geht dann auch nur innerhalb der Klasse Class2. Hier handelst du wieder im Subclass Scope.
 

hexx

Mitglied
Allein warum das so ist, kapiere ich nicht. In meinen Augen ist das ein Fehler des Compilers. Wenn "protected" bedeutet, dass Instanzen von Unterklassen auf die Methoden und Felder der Oberklasse zugreifen können (unabhängig vom Package der Ober- und Unterklassen), warum funktioniert das dann hier nicht?

Weil die Definition, so wie du sie schreibst, zwar häufig verwendet, aber eben unpräzise und nicht richtig ist.

Jodo, kannst Du mir Deine Erklärung mit dem anonymen Objekt genauer erklären? Was ist ein anonymes Objekt?

Ein anonymes Objekt ist ein Objekt, das man direkt "anonym" benutzt, ohne es einer Variablen zuzuweisen:

Java:
(new MyClass()).toString()
 

Bazinga

Mitglied
Allein warum das so ist, kapiere ich nicht. In meinen Augen ist das ein Fehler des Compilers. Wenn "protected" bedeutet, dass Instanzen von Unterklassen auf die Methoden und Felder der Oberklasse zugreifen können (unabhängig vom Package der Ober- und Unterklassen), warum funktioniert das dann hier nicht?
Der Zugriff auf protected Elemente (aus einem anderen package) ist nur erlaubt, wenn es sich um dasselbe Objekt (nicht Klasse!) handelt. Bei diesem Beispiel:
Java:
Class c1;
// ...
c1.doSomething();
ist c1 für den Compiler eine fremde Instanz (nicht this) und der Zugriff wird zurecht (laut Sprachspezifikation) verweigert. Nur der Zugriff auf Elemente desselben Objektes sind erlaubt, also z.B.:
Java:
doSomething(); // bzw. this.doSomething();
super.doSomething();
 

flopalko

Bekanntes Mitglied
Dieser Code ist eine ausgezeichnete Zusammenfassung - genau darum geht es!

Allein warum das so ist, kapiere ich nicht. In meinen Augen ist das ein Fehler des Compilers. Wenn "protected" bedeutet, dass Instanzen von Unterklassen auf die Methoden und Felder der Oberklasse zugreifen können (unabhängig vom Package der Ober- und Unterklassen), warum funktioniert das dann hier nicht?

Jodo, kannst Du mir Deine Erklärung mit dem anonymen Objekt genauer erklären? Was ist ein anonymes Objekt?



Und das verstehe ich auch nicht. Natürlich geht es mir nur um die Methoden und Felder der Objekte und nicht die der Superklasse. Was sind Methoden und Felder der Klasse?

Danke
Keksi
Wieso soll das ein Compilerfehler sein? Die Antwort darauf wurde dir bereits gegeben:


Java Language Specification

  • Innerhalb einer Unterklasse, kann man auf die ererbten protected Elemente (Zur Verdeutlichung: Zugriff mit super.* möglich) der Oberklasse zugreifen, egal in welchem Paket die Unterklasse liegt.
  • Von außen (über eine Variable vom Typ der Oberklasse) kann man nur innerhalb des Pakets auf die protected Elemente zugreifen. Auch wenn die Variable innerhalb der Unterklasse deklariert ist.
Sobald du eine Variable vom Typ der Oberklasse hast kannst du in einem anderen Package nicht mehr auf protected Methoden zugreifen. Du legst dir also eine Variable vom Typ Class1 in Class2 als Instanzvariable an und willst dann dort (in einem anderen Package) auf Methoden zugreifen, die protected sind. Klar erbt Class2 diese Methoden, aber du hast halt eine Variable vom Typ Class1 und versuchst es ohne Cast (im gleichen Package wäre das ja auch vollkommen in Ordnung, nur in einem anderen Package ist das halt einfach nicht erlaubt und funktioniert deshalb nicht).
Alles in allem bleibt festzuhalten, dass sich der Code genauso verhält wie von der Sprache definiert ;)
 

Jodo

Aktives Mitglied
[...]
(1)
Allein warum das so ist, kapiere ich nicht. In meinen Augen ist das ein Fehler des Compilers. Wenn "protected" bedeutet, dass Instanzen von Unterklassen auf die Methoden und Felder der Oberklasse zugreifen können (unabhängig vom Package der Ober- und Unterklassen), warum funktioniert das dann hier nicht?

[...]
(2)
Und das verstehe ich auch nicht. Natürlich geht es mir nur um die Methoden und Felder der Objekte und nicht die der Superklasse. Was sind Methoden und Felder der Klasse?

Danke
Keksi

Du musst zwischen einer Klasse und Instanzen der Klasse (Objekten) unterscheiden. Deine 1.Aussage (1) ist ja im Prinzip richtig. Unterklassen wollen auf die Methoden/Felder der Superklasse zugreifen, sprich alles was in der Superklasse deklariert ist (und nicht private ist) soll auch die Unterklasse haben.
Ein Objekt von Klasse A kennt alle Methoden/Felder der Superklasse S. Daher kann es mit
Code:
super
auf diese zugreifen. Beispiel:

Code:
public class S {
    protected void print() {
        System.out.println("Ich bin ein S-Typ");
    }
}
Code:
public class A extends S {
    @Override
    protected void print() {
        System.out.println("Ich bin ein A-Typ");
        System.out.print("Mein Vater sagt: ");
        super.print();
    }

    public static void main(...) {
        A a = new A();
        a.print();
    }
}
Als Ausgabe erhältst du dann:
Code:
Ich bin ein A-Typ
Mein Vater sagt: Ich bin ein S-Typ

Was aber eben nicht geht, ist ein Zugriff bei anderen Objekten, deren Methoden/Felder protected sind und deren Klasse in einem anderen package liegt.
Als Beispiel kann ich hier nur nochmal auf das "public-machen" dieser Elemente verweisen (Code-Beispiel des vorherigen Posts). Ich finde daran wird es deutlich, wieso der Zugriff auf Objekte durch protected so geregelt wird. Instanzen einer Klasse, die in dem selben package wie die Superklasse deklariert ist, kannst du ja immer vertrauen. Da man aber auch von außerhalb dieses packages erben kann, wäre es dann möglich diese proctected-Element public zu machen und somit jedem den Zugriff auf fremde Objekte ermöglichen. Und das ist ja nicht Sinn der Sache.
Deine 2.Aussage (2) ist falsch. Sinn von Vererbung ist es, dass A die selben Methoden/Felder besitzt wie die Superklasse S und nicht dass A Objekte vom Typ S manipulieren kann.
Vererbung findet auf Klassen-Ebene statt und nicht auf Objekten. Sprich du willst Zugriff auf die Methoden/Felder der Superklasse nicht auf die der Objekten dieser Klasse.


Ich weiß nicht inwiefern du dich mit Java und Programmierung beschäftigst (Studium/Hobby) aber bei uns an der Uni wurde von Anfang an sehr viel Wert auf OOP gelegt und dass wir die Konzepte verstehen.

(Da ich jetzt öfters Teile geändert hab und immer mal wieder Vorschau gedrückt, hoffe ich alles ist noch klar, richtig und nicht ohne Zusammenhang:D)
 
Zuletzt bearbeitet:

Mujahiddin

Top Contributor
Noch so als Anhang, da das hier anscheinend keiner erwähnt hat: die Methoden
Code:
finalize()
und
Code:
clone()
der Klasse
Code:
java.lang.Object
sind ebenfalls protected. Du kannst die Methode finalize() überschreiben, aber du kannst sie nicht von anderen Objekten aufrufen (nur von dir selbst).
Code:
finalize()
ist im Grunde der letzte Schieß, den dein Objekt grunzt, bevor es vom Garbage Collector geschrottet wird.
Sind finde ich die besten Beispiele für protected.

Grüße!
 
S

SlaterB

Gast
meint das mehrmals erwähnte "nicht von anderen Objekten aufrufen" wirklich Objekte, oder ist es nicht eher so,
dass wenn Klasse B von Klasse A ergebt, Klasse B auf alle Klasse B-Variablen, die auch andere Objekte von Klasse B enthalten können als das eigene bzw. statisch überhaupt kein eigenes, die protected-Methoden von A aufrufen darf?
also eher "nicht von anderen Klassen aufrufen"
 

Jodo

Aktives Mitglied
Naja bei anderen Objekten, der eigenen Klasse geht es. Ein Objekt der Klasse B kann ja auch allen anderen B-Objekten trauen, da deren Klasse an der Implementierung beteiligt ist.

Aber "nicht von anderen Klassen aufrufen" dürfte nicht stimmen, weil du ja mit
Code:
super
explizit eine Methode einer anderen Klasse aufrufen kannst.
 

Noctarius

Top Contributor
Code:
finalize()
ist im Grunde der letzte Schieß, den dein Objekt grunzt, bevor es vom Garbage Collector geschrottet wird.

Ich frage mich wieso du das noch erwähnt hast? Lass mich raten, du bist einer der finalize()-Verfechter? ;-)

Die Methode ist Dreck und sollte nicht zum Aufräumen genutzt werden. Nirgends ist sichergestellt, dass diese Methode aufgerufen werden muss und meiner Meinung nach sollte die JRE langsam mal um solche hässlichen, schon seit langem als Fehler erkannten, Dreck bereinigt werden.
 
S

Spacerat

Gast
[OT]
Code:
finalize()
ist im Grunde der letzte Schieß, den dein Objekt grunzt, bevor es vom Garbage Collector geschrottet wird.
Was ist das denn? :lol:
Ob das Objekt bei [c]finalize()[/c] noch quiekt ist dem GC doch herzlich egal. Pass' auf, dass Javaentwickler deswegen in Zukunft nicht vegetarisch entwickeln (z.B. PHP, VB oder ähnlichem XD). Nein, im Ernst: finalize ist halt dazu da, dass das Objekt vorm schreddern noch Ressourcen freigeben kann, z.B. irgendwelche Listener (diese werden gemultiplexed) removen, damit diese vom GC schneller oder überhaupt gefunden werden.[/OT]
[OT]
protected: Zugriff von Klassen im selben Package, nicht von Klassen außerhalb; wird geerbt
Falsch: ;) Genau andersherum. Member, Methoden, Klassen und Konstruktoren ohne Modifier sind Packageprivate, mit protected können diese auch nach ausserhalb des Package vererbt werden. So hat's Noctarius doch auch verständlich gemacht, oder nicht?[/OT]
Noch was zum Thema: "protected static" ist mir noch nicht untergekommen. Statischer Kontext ist ja nicht vererbbar, deswegen machts wohl auch keinen Sinn.
 
Zuletzt bearbeitet von einem Moderator:

Mujahiddin

Top Contributor
Nein, ich bin kein finalize-Verfechter... Ich hab bisher auch wirklich kein bisschen darüber gelesen, nur eben die API "this method is called by the garbage collector"
Und wenn der Garbage Collector drüberfährt, dann ruft er doch die Methode auf?
Naja keine Ahnung, wie gesagt, kenn mich damit nicht aus. Ich wollte nur erwähnen, dass man für "protected" keine eigenen Pakete erstellen muss. Es liegt praktisch schon in der Klasse Object!
 

xehpuk

Top Contributor
Aber nur wenn der GC möchte.
Also die Dokumentation der Methode als auch an mehreren Stellen in der JLS steht, dass der GC die Methode (zwingend) aufruft. Da steht nichts vom Willen des GC.

Dass sie nicht aufgerufen wird, wenn etwa
Code:
System.exit()
aufgerufen wird, leuchtet ein. Aber wozu würde man dann noch aufräumen wollen? Werden dabei nicht alle Ressourcen freigegeben?
 

Noctarius

Top Contributor
Natürlich entscheidet der GC nicht ob er die Methode aufruft, das war doof ausgedrückt, stimmt. Aber der GC entscheidet wann und ob er aufräumen möchte und diesen Zeitpunkt kannst du nicht bestimmen. Das meinte ich mit GC-Willen. Es gibt einfach keine Gewähr ob die finalize()-Methode aufgerufen wird oder nicht und gerade bei File- und / ober Windowhandles kann dies ein Problem geben, wenn die JVM genug Speicher hat.
Ergo verlässt man sich nicht auf finalize()-"Dekonstruktoren" wie sie ja von C++lern immer gerne genannt werden. Ich hatte erst neulich noch eine Diskussion mit einem der "Java hasst", weil es keine Destruktoren gibt.

Auf die Frage hin was an [c]x.delete();[/c] schlimmer ist als an [c]delete x;[/c] kam keine Antwort. Irgendwie ist finalize() so ein Überbleibsel aus den Anfängen als man noch von C++ kam und wird seit Jahren als einer der größten Fehler in Java angesehen.
 
S

Spacerat

Gast
Da steht nur, dass sie vom GC aufgerufen wird, wenn ein Objekt seine letzte Referenzierung verliert (also eigentlich immer, wenn GC sich anschickt aufzuräumen. XD).
Bei der Insel kann man zwischen den Zeilen auch heraus lesen, dass man finalize zusätzlich zum selber aufräumen auch implementieren sollte, wenn man die dort genannten Dinge verwendet. Meiner Meinung nach gehören AWT-EventListener auch dazu.
Soweit ich das überblicke existiert finalize eigentlich nur wegen diesem gemultiplextem Kram (ich weis nur, das Eventlistener so angelegt werden). Dort enthaltene Objekte können nämlich nur wieder entfernt werden, solange eine Referenz zu diesem Objekt existiert, letztendlich also durch das Objekt selber. Eventlistener sollten also diese finalize()-Krankheit sehrwohl implementieren, um sich selbst aus dieser Kette zu entfernen. Wenn niemand ein weiteres Beispiel für dieses Multiplexing kennt (evtl. LinkedList), bleiben diese Listener wohl auch die einzigen, wo finalize() überhaupt Sinn macht.
[EDIT]Hab' noch mal nach geschaut... Das Ganze Ding heisst AWTEventMulticaster. Wie komm' ich blos auf Multiplex. Sorry, für Verwechslungen. :oops:[/EDIT]
 
Zuletzt bearbeitet von einem Moderator:

xehpuk

Top Contributor
Ach so, es ist nicht sichergestellt, dass
Code:
finalize()
aufgerufen wird, weil nicht sichergestellt ist, dass der GC aufräumt (wenn viel Speicher da ist). Und deswegen soll man Aufräumaktionen zumindest nicht nur in
Code:
finalize()
erledigen.

Bei etwa
Code:
FileInputStream
wurde dies genutzt, damit das Ausmaß nicht zu groß wird, falls ein Entwickler vergessen hat, den Stream zu schließen. Dann hätte man dies doch direkt bei
Code:
InputStream
machen können? Andererseits ist das vielleicht auch nicht so gut, weil dieser Fehler eventuell erst später oder gar nicht entdeckt wird.

Mit try-with-resources sollte das aber sowieso kein großes Thema mehr sein.
 
S

Spacerat

Gast
So hab' ich das zumindest verstanden. Aufräumen sollte man immer selbst. Bei dieser Listener-Geschichte ist das aber leider nie so einfach. Ich verwende ja auch gerne mal anoyme Listener, also
Java:
myComponent.addActionListener(new ActionListener() {
  public void actionPerformed(ActionEvent ae) {
    // ... usw
  }
});
Es gibt anschliessend keine konkrete Instanz des Listeners mehr, die man aus dem Multicaster entfernen könnte. Man könnt evtl. noch "getListeners()" der Componente bemühen und rigoros alle anonymen Listener entfernen... tolle Sache das, so räumt man auf. :lol:
Bei solchen Konstrukten sollte man deswegen auch immer dran denken, finalize zu überschreiben, sonst wundert man sich am Ende noch über Mem-Leaks.
In der Windowsversion von Java mache ich mir über ein fehlendes close von FileInputStreams keine sorgen. Das macht Windows beim Abbruch der VM (sowie bei anderen Programmen auch) selbst. Deswegen unterscheide ich da auch gewaltig zwischen FileIn- und Output. In Dateien geschiebenes ohne close und JVM-Ende sorgen da nämlich für Datenverlust.
 
Zuletzt bearbeitet von einem Moderator:
Ähnliche Java Themen
  Titel Forum Antworten Datum
K OOP Vererbtes Field über Class Objekt Java Basics - Anfänger-Themen 3
K Sichtbarkeit protected: Attribute trotzdem aufrufbar. Java Basics - Anfänger-Themen 4
H Kapselung protected aber in einer Kindklasse nicht zugänglich Java Basics - Anfänger-Themen 5
B Vererbung - Sichtbarkeitsmodifikation - protected Java Basics - Anfänger-Themen 10
S Zugriff auf protected Fields = guter Programmierstil? Java Basics - Anfänger-Themen 11
S protected = nicht protected? Java Basics - Anfänger-Themen 9
Aprendiendo Zwei Fragen und ein geerbtes "protected"-Attribut Java Basics - Anfänger-Themen 2
wilmaed protected class Java Basics - Anfänger-Themen 0
K Vererbung protected NUR für Unterklassen? Java Basics - Anfänger-Themen 17
M Schlüsselworte Ohne Modifizierer gleichbedeutend mit protected? Java Basics - Anfänger-Themen 6
K Protected und Private Deklaration Java Basics - Anfänger-Themen 8
B Vererbung Probleme bei Zugriff auf protected-Methoden in einer Unterklasse Java Basics - Anfänger-Themen 27
J protected Methoden Java Basics - Anfänger-Themen 8
W Frage public protected konstruktor Java Basics - Anfänger-Themen 6
B Kapselung Klasse private, Konstruktor protected Java Basics - Anfänger-Themen 10
T Kapselung: public-Methoden in protected-Klassen Java Basics - Anfänger-Themen 3
A protected Java Basics - Anfänger-Themen 18
F Ewiges Leid mit "protected" (oder "wie der beste Freund eine hinrücks betrügt") Java Basics - Anfänger-Themen 26
A Frage zu Protected in SubSubKlasse Java Basics - Anfänger-Themen 4
G Protected Variablen außerhalb der eigenen Klassenhierarchie sichtbar Java Basics - Anfänger-Themen 5
N Wann muss eine Methode - protected sein wann public wann. Java Basics - Anfänger-Themen 5
stekoe2000 protected abstrac class Java Basics - Anfänger-Themen 3
B public und protected Java Basics - Anfänger-Themen 11
S Veränderung von Protected Daten durch Übergabe? Java Basics - Anfänger-Themen 3
G Public ,private,protected Java Basics - Anfänger-Themen 1
M Konstruktor protected machen Java Basics - Anfänger-Themen 7
H protected Java Basics - Anfänger-Themen 2
U public, private, protected und "default access" - Java Basics - Anfänger-Themen 14
V Auf protected ArrayList von anderer Klasse zugreifen Java Basics - Anfänger-Themen 4
J protected und Standard Sichtbarkeit Java Basics - Anfänger-Themen 2
M Jede Variable als private, protected etc. deklarieren? Java Basics - Anfänger-Themen 7
P protected funktioniert nicht? Java Basics - Anfänger-Themen 5

Ähnliche Java Themen

Neue Themen


Oben