2017-05-30 4 views
0

Ich habe drei Klassen.Warum kann keine Unterklasse die Methode der Elternklasse sehen?

Klasse A

public class A { 

} 

Klasse B

public class B extends A { 

    public void hello(){ 
     System.out.println("hello"); 
    } 
} 

Klasse C

public class C extends B { 

} 

Klassenarbeit

public class Test { 

    public static void main(String[] args) { 
     A a = new C(); 
     a.hello(); // The method hello() is undefined for type A 
    } 
} 

Der obige Code wird nicht kompiliert, weil es einen Fehler meldet, die „für Typen A nicht definiert ist, das Verfahren hallo()“

Meine Frage ist, da „a“ ein C Objekt ist, warum a.hello() nicht die Verwendung hello() Methode in der Elternklasse von B?

Wenn ich ein Hallo-Methode A Klasse hinzufügen, erst dann wird der Code über die Verwendung der hello() von B-Klasse, aber warum habe ich hello()-A Klasse hinzuzufügen, um die Methode von B Klasse zu bedienen?

+2

Ihre Variable 'a' könnte einen Verweis auf eine andere Unterklasse von' A' enthalten (wie 'D'), die keine Methode' hallo() 'liefert - der Compiler weiß es einfach nicht. Daher erlaubt der Compiler nur Aufrufe von Methoden, die für die Klasse A definiert sind. –

+0

Identisch mit 'Object o = new String (" 123 ");' und nicht in der Lage sein, 'o.length();' zu verwenden. Wenn Sie jedoch o an einen String übergeben, können Sie die Methoden von String verwenden. –

+1

Es klingt, als ob Sie erwarten würden, dass Ihre Definition von 'B' Ihre Definition von' A' ändert, indem Sie dessen Funktionalität "erweitern"? Denkst du darüber nach? Denn wenn das stimmt, ist das falsch. Wenn Sie 'B' und' C' definieren, tun Sie nichts mit 'A'. Eher "B" und "C" "kopieren" oder "erben" die Definition von "A" als ihren Ausgangspunkt, und dann hat alles, was Sie in ihnen definieren, auch Zugriff auf die Definition von "A". – dantiston

Antwort

2

A a Top-Level-Klasse in Ihrer Hierarchie. Es sieht nur die Methoden, die darin definiert sind. Von den Unterklassen definierte Methoden sind für A nicht zugänglich. Sicher, Sie können C der Variablen A zuweisen, und Sie können es dann verwenden, wo A verwendet werden kann, aber jetzt wird C auf Methoden beschränkt, die A hat.

Es macht Sinn, wenn Sie darüber nachdenken. Wenn Sie einen Typ definieren (A), erwarten Sie, dass er sich gemäß Ihrer Definition verhält (was nichts über C Felder und Methoden enthält). Sie erwarten nicht, dass es plötzlich alles hat, was Unterklassen definiert haben könnten (stellen Sie sich zum Beispiel eine Situation vor, in der hundert Leute Ihre Klasse auf verschiedene Arten erweitert haben - Spitzenklasse würde unglaublich aufgebläht und breit werden).

Aus diesem Grund erweitern Unterklassen Elternklassen - sie fügen zusätzliche Funktionalität hinzu, die nicht im Elternteil definiert ist (und wahrscheinlich auch nicht sein sollte). Der Elternteil selbst kennt jedoch die zusätzliche Funktionalität nicht und kann sie nicht verwenden. Jede Klasse kann nur das verwenden, was sie definiert oder ihre Eltern definiert haben. Wenn Sie daher dem Typ des übergeordneten Elements C zuweisen, werden nur die Methoden abgerufen, die A bekannt sind (aber mit der Implementierung C).

Bedenken Sie:

public class Animal { 
    public void walk() { 
     System.out.println("Walking"); 
    } 
} 


public class Dog extends Animal { 
    public void bark() { 
     System.out.println("Woof"); 
    } 

    @Override 
    public void walk() { 
     System.out.println("Doggy walk"); 
    } 

    public static void main(String[] args) { 
     Dog dog = new Dog(); 
     Animal animal = new Animal(); 
     Animal animalDog = new Dog(); 
     dog.walk(); // "Doggy walk" 
     dog.bark(); // "Woof" 
     animal.walk(); // "Walking" 
     animal.bark(); // Error: bark() is not defined in the Animal class 
     animalDog.walk(); // "Doggy walk" 
     animalDog.bark(); // Error - Animal class has no bark() 
    } 
} 

Da wir Dog zu Animal Typ zugeordnet, kann es nur Methoden, die in Animal Klasse definiert sind. Beachten Sie jedoch, dass das Verhalten das ist, das Sie in der Klasse Dog für dieselbe Methode definiert haben.

Wenn Sie müssen die Methode verwenden, und aus irgendeinem Grund nicht auf einen Typ zugeordnet, der die Methode hat, sollten Sie es entsprechend gegossen, z.B .:

((Dog) animalDog).bark(); // "Woof" 
1

Wenn Sie a als Objekttyp A (A a = new C();) definieren, hat es nur Zugriff auf die Member und Methoden des Typs A. Um das zu tun, was Sie wollen, definieren Sie entweder hello() am Typ A oder definieren Sie a als Objekt vom Typ B (B a = new C();). Dies liegt daran, dass der Compiler nachverfolgt, welche Methoden zur Verfügung stehen. Wenn aus irgendeinem Grund, Sie eigentlich keinen Zugriff auf die Instanziierung haben, aber Sie müssen etwas von B zugreifen, aber es ist übergeben Sie als A Objekt, dann können Sie es Stimmen:

if (a instanceof B) (B a).hello(); 
else throw new Exception(); 
1

Es geht um Variablentypen. Sie instanziieren die C-Klasse, behandeln aber das Ergebnisobjekt als A. Die Schnittstelle der Klasse A enthält keine "Hallo" -Methode, weshalb Sie sie in Ihrem Beispiel nicht verwenden können.

Um das Problem zu lösen, sollten Sie entweder Ihre Methode A oder Update-Typen der Variablen B. hinzufügen

1

Wenn Sie eine Variable als mit der Art der übergeordneten Klasse deklarieren, können Sie nur den Zugriff (public) Methoden und Mitgliedsvariablen der Oberklasse durch diese Variable.

0

In Methode überschreiben Sie gleiche Methode in Super class.In dieses Szenario der meist Super-Klasse ist A

1

In Ihrer Frage A eine Elternklasse von B, B ist die Elternklasse von C (dh haben sollten A-> B-> C) und Sie erstellen das Objekt der C-Klasse über A. Also, nach Ihrem Programm zuerst versuchen, die hallo() -Methode in A-Klasse zu finden, weil es eine super Elternklasse von C ist, die nicht Hallo() -Methode ist, deshalb zeigt es einen Fehler.

1

Ich denke, Sie sind ein wenig verwirrt darüber, wie Polymorphie funktioniert. Du sagst, dass "a" ein "c" Objekt ist, was eine irreführende Annahme ist, die viele Anfänger machen. Also hier ist ein Beispiel, um zu veranschaulichen, was passiert:

Angenommen, Sie haben eine "Tier" -Klasse, die um eine separate "Dog" -Klasse erweitert wird, weil ein Hund ein Tier ist. So können wir schreiben:

Animal someAnimal = new Dog(); 

Die obige Aussage kann neu geschrieben werden als:

Dog someDog = new Dog(); 
Animal someAnimal = someDog; 

die zeigt, dass ein Hund-Objekt als Tier Objekt gespeichert werden kann. Warum? Weil ein Hund ein Tier ist. Sie können nicht tun

Dog someDog = new Animal(); 

weil ein Tier ist nicht [unbedingt] ein Hund.

Dies verweist auf Ihre ursprüngliche Behauptung. Ihr „a“ ist kein „c“ Objekt, weil man nie wie etwas geschrieben:

C a = new A(); // sidenote : this will give you error, as you are saying the analogous Animal is a Dog 

Als Ergebnis der Superklasse (die „A“) kann diese Methoden nicht zugreifen aus der Unterklasse (die in diesem Fall ist "B"), weil Superklassen nicht von Unterklassen erben (es ist umgekehrt).

Verwandte Themen