2014-06-26 52 views
0

爲什麼我們不能通過子類引用變量訪問超類​​對象..i有一個代碼來討論我的問題。通過子類引用變量訪問超類​​對象

class A 
{ 
    void set()  
    { 
    System.out.println("i am in a"); 
    } 
} 

class B extends A 
{ 
    void set() 
    { 
    System.out.println("i am in b"); 
    } 

    public static void main(String args[]) 
    { 
    A instance=new B(); //line 
    instance.set(); //this would call set() in B. 
    B in=new A(); //But this line gives error 
    } 
} 

任何人都可以幫忙嗎?

+0

靜態方法不是多態的。在你的代碼中,'instance.set();'會在類'A'中調用'set()'。通過實例變量調用靜態方法是不好的做法。你應該調用'A.set()'或'B.set()'。當然,我猜你實際上並不需要靜態方法。 – GriffeyDog

+1

用'動物'和B用'蝙蝠'弱智地代替'A'。這應該讓你更清楚爲什麼當你試圖在'Bats'變量中放入一個'Animal'時,java會感到不安;你可以調用'.fly()'方法(其中'Bat'只有'Animal'沒有),並且所有的地獄都會崩潰。 [我假設你在這裏使用靜態是偶然的,如果不是這裏有更多的錯誤] –

+1

[在java中,我們可以將超類Object傳遞給子類引用嗎?](http://stackoverflow.com/問題/ 24384547/in-java-can-we-pass-superclass-object-to-subclass-reference) – awksp

回答

2

子類可能有超類沒有的成員,因此不允許將超類實例分配給子類引用。
想象一下B有另一種方法,subMethod()。如果你能在A實例分配給一個B參考,你可以寫下面的代碼:

B example = new A(); 
example.subMethod(); 

這將打破,因爲A沒有subMethod()

另一種方法很好,因爲子類總是擁有超類的一切。

另外,請注意,static方法不能被覆蓋,只有實例方法是多態的。

+0

謝謝:)明白了! – newuser

+0

@ user3779571:非常歡迎。不要忘記註冊(當你有足夠的聲譽時)有用的答案,並接受你認爲最能回答你問題的答案。 – Keppil

0

繼承是分層的。

您可以創建一個類Person和類Karl extends Person,與sayName()方法,

那麼當你創建一個Karl它會融入Person變量,但不是每個PersonKarl

如果您想顯式調用超類,則可以在類Karl中創建函數saySuperName(),您可以在其中調用super.sayName()

參見:http://docs.oracle.com/javase/tutorial/java/IandI/super.html

1

採用類似於您的問題另一個例子,

class Animal 
{ 
    void set()  
    { 
    System.out.println("i am in animal"); 
    } 
} 

class Dog extends Animal 
{ 
    void set() 
    { 
    System.out.println("i am in dog"); 
    } 
    void bark(){ 
    System.out.println("woof woof"); 
    } 

    public static void main(String args[]) 
    { 
    Animal instance=new Dog(); //line 
    instance.set(); //this would call set() in B. 
    Dog in=new Animal(); //But this line gives error 
    } 
} 

繼承遵循is-a關係,現在我們可以說,狗伸出動物和狗,一個動物。這就說得通了。但動物是 - 狗沒有意義。

當您編寫Animal instance=new Dog();時,您正在將Dog對象分配給Animal引用,這聽起來很直觀,LHS(Animal實例)也是引用變量,引用變量的作用是決定調用哪些函數對象(那些存在於動物中的對象,例如set()),因爲它是動物類的類型,所以您不能使用實例調用bark()方法,因爲它是Animal類型的對象,但是您可以調用set()。現在有兩個版本的set()其中一個出現在Animal類和Dog類中,現在要調用哪一個取決於RHS(新Dog();),因爲RHS是一個實例並且類型爲Dog(),Dog中的版本爲set()叫做。總而言之,請參閱以下代碼並在註釋中輸出: -

Animal a1=new Animal(); 
a.set();// output- i am in animal 

Dog d1=new Dog(); 
d.set(); //output- i am in dog 
d.bark; //valid and output- woof woof 

Animal a2=new Dog(); 
a2.set();//output- i am in dog 
a2.bark();// compilation error, you cannot refer to this method since it is not present in Animal class. 

Dog d2=new Animal(); // compilation error 
+0

感謝您的解釋:) – newuser