2017-05-30 82 views
0

我有三個班。爲什麼不能在子類中看到父類的方法?

A類

public class A { 

} 

B類

public class B extends A { 

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

C類

public class C extends B { 

} 

類檢驗

public class Test { 

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

上面的代碼將無法編譯,因爲它報告讀取錯誤「的方法你好()是不確定的A型」

我的問題是,因爲「A」是一個C對象,爲什麼不a.hello()使用在B的父類中的hello()方法?

如果我添加一個hello方法A類,最後才上面的代碼使用hello()從B級,可是爲什麼我要加hello()A級才能使用的方法,從B類?

+2

您的變量'a'可能包含對'A'的另一個子類(如'D')的引用,它沒有提供方法'hello()' - 編譯器根本不知道。因此,編譯器只允許調用爲類「A」定義的方法。 –

+0

和'Object o = new String(「123」);'不能使用'o.length();'然而,如果你將o賦給一個String,那麼你可以使用String的方法。 –

+1

這聽起來像你可能希望你定義'B'通過「擴展」它的功能來改變'A'的定義嗎?那是你在想什麼?因爲,如果是這樣,那是不正確的。通過定義'B'和'C',你對'A'什麼都不做。相反,「B」和「C」將「A」的定義「複製」或「繼承」爲起點,然後您在其中定義的任何內容都可以訪問「A」的定義。 – dantiston

回答

2

A是您的層次結構中的頂級課程。它只能看到在其中定義的那些方法。 A無法訪問由其子類定義的方法。當然,您可以將C分配給變量A,然後您可以在任何可以使用A的地方使用它,但現在C將僅限於A具有的方法。

當你考慮它時它是有道理的。當你定義一個類型(A)時,你期望它的行爲符合你的定義(不包括任何關於C字段和方法的內容)。你不希望它突然擁有所有可能定義的子類(例如,想象一下,有一百人以各種方式擴展你的班級 - 高級班將變得非常臃腫和廣泛)。

這就是爲什麼子類擴展父類的原因 - 它們添加了不在父類中定義的附加功能(也可能不應該)。但是,父母本身並沒有意識到附加功能,也無法使用它。每個類只能使用它定義的或其父代定義的內容。因此,當您將C分配給父類型時,您只會獲得A知道的那些方法(但使用C的實現方式)。

考慮:

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() 
    } 
} 

因爲我們分配給Dog類型Animal,它只能使用在Animal類中定義的方法。但請注意,該行爲將是您在Dog類中爲同一方法定義的行爲。

如果必須使用的方法和你沒有它分配給了該方法的類型某種原因,你應該相應方法進行投放,例如:

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

當您將a定義爲A類型對象(A a = new C();)時,它只能訪問類型爲A的成員和方法。要做你想做的事情,可以在A上定義hello(),或者將a定義爲BB a = new C();)類型的對象。這是因爲編譯器正在跟蹤它可用的方法。如果由於某種原因,你實際上沒有訪問實例,但你需要從B訪問的東西,但它交給你作爲一個A對象,那麼你可以將它轉換:

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

這是所有關於變量類型。你正在實例化C類,但將結果對象視爲A.類的接口不包含'hello'方法,這就是爲什麼你不能在你的例子中使用它。

爲了解決這個問題,就應該把你的方法添加到一個或B.

1

變量的更新類型在聲明一個變量爲具有超類的類型,你只能訪問(公共)方法和通過該變量的超類成員變量。

0

在方法重寫,你應該在超級class.In同樣的方法這種情況下最超類是A

1

在你的問題中是一個父類B的,B是父類的Ç (即A-> B-> C),並通過A創建C類的對象。所以,首先根據你的程序,它試圖在A類中找到hello()方法,因爲它是C的超級父類,它沒有定義hello()方法,這就是它顯示錯誤的原因。

1

我認爲你對多態如何工作有點困惑。你說「a」是一個「c」對象,這是許多初學者誤導的假設。所以這裏有一個例子來說明發生了什麼:

假設你有一個「動物」類,它由一個單獨的「狗」類擴展,因爲狗是一種動物。因此,我們可以這樣寫:

Animal someAnimal = new Dog(); 

上面的語句可以改寫爲:

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

這表明一個Dog對象可以存儲爲一個Animal對象。爲什麼?因爲狗是一種動物。你不能這樣做

Dog someDog = new Animal(); 

因爲動物並不一定是狗。

這點回到你原來的斷言。您的「一」是不是「C」的對象,因爲你從來沒有寫過這樣的:

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

其結果是,超類(即「A」)不能訪問從子類的方法(在這種情況下,是「B」),因爲超類不會從子類繼承(這是相反的)。

相關問題