[英]Java Interface question regarding polymorphism
所以我有這個:
interface C {
void shutUp();
}
class A {
public void speak() {
System.out.println("Class a");
}
}
class B extends A implements C {
public void shutUp() {
System.out.println("Saying nothing...");
}
public void speak() {
System.out.println("Class B");
}
}
如果我這樣做,它將起作用:
A obj = new B();
obj.speak()
但是我不能做obj.shutUp()
為什么不呢? 我覺得我對一些非常基本的東西感到困惑。
謝謝!
A的靜態類型未連接到C,因此您無法執行此命令,這將是相同的:
A obj = new A();
obj.shutUp();
(這顯然是非法的。)
唯一可以同時使用兩者的人是B
B obj = new B();
obj.shutUp();
obj.speak();
這都與Java是static typing
這一事實有關
因為A不是C-它沒有實現接口-並且您不能以這種方式實例化接口,因為沒有默認的構造函數。
類型A的引用沒有方法shutUp()
,因此它不起作用也就不足為奇了。
而且您的代碼使用了錯誤的關鍵字:這是Java的class
和interface
。 案件很重要。
通過說A obj = new B(); 您正在將代碼與接口的特定實現分離。 因此,obj將無法訪問在類b中實現的shutup()函數。
您的obj
具有類A
接口,因為它是變量的類型。
obj
的類型定義為A
; 因此, obj
只能使用A
可用的成員。 因為C
繼承自A
,所以C
具有被視為A
形式的所有成員,這就是為什么它允許您在A
變量中創建新C
的原因。 只有將其強制轉換為C
類型,您才能使用屬於C
所有成員。
您的問題是錯誤的:您無法創建C對象,因為它是接口-所以我認為您想創建B對象,然后:
這是因為obj是A而不是C,要使用shutUp方法,您可以:
((C) obj).shutUp() // cast to C type
((B) obj).shutUp() // cast to B type
或聲明:
B obj = new B();
obj.shutUp();
要么:
C obj = new B(); // (!) but: you can't (without casting) call speak method
obj.shutUp();
obj =新的C();
因為C是接口,所以您不能創建接口的實例。 請更正問題。
為什么不能在obj上調用shutUp的原因是:
obj不是對象,而是指針或引用。 執行新B()時創建的對象是一回事,obj(或“如何使用該對象”)是另一回事。 您可以在引用(在本例中為obj)的幫助下使用對象,該引用使您可以訪問實際對象的不同側面。
如果用於訪問對象的引用是引用當前對象的類型(即,具有相同的名稱),則可以通過此引用訪問整個對象。 否則,您只能訪問引用類型可以看到的對象部分。
在您的示例中,引用類型為A,即obj僅看到其引用的任何對象的A部分。 因此,即使對象具有這些行為,它也無法訪問對象的B / C部分。
其他人已經回答了這個問題,但是請注意,有一種方法可以在不強制轉換為B
或C
情況下調用shutUp()
:
A obj = new B();
try {
Method shutUp = obj.getClass().getMethod("shutUp", null);
shutUp.invoke(obj, null);
}
catch (Exception ignored) {}
A obj = new B();
在這里,您將創建類型為“ A”的“ B”實例。 即,您說的是“我想創建一個對象B並將其命名為類型A的obj”。
在A類中,只有一種可訪問的方法。 它沒有實現C
public void speak() {}
為了能夠訪問類B的所有方法,您應該創建“ B”類型的“ B”實例
B obj2 = new B();
這樣您就可以訪問
public void shutUp() {}
這是因為實現類“ C”的是B。
能夠使用“ obj”訪問這兩種方法的一種方法是使A工具C
由new B()
創建的對象可用作三種類型的對象-A,B或C。但是您不能聲明多種類型的變量。
由於B是A和C的子類型,因此您可以將其實例用作任何這些類型的實例。 例如
B o = new B();
A aO = o;
C cO = o;
現在你可以使用o
來訪問speak
和shutUp
方法,您可以使用aO
訪問speak
方法和cO
訪問shutUp
方法。 不管使用哪個變量,調用的方法都是相同的,因為這些變量都引用相同的對象。 為什么不能使用aO
來調用Java中的shutUp
原因是因為您使用沒有這種方法的類型聲明了變量。 盡管您知道該特定對象確實具有該方法,但一般而言並非如此。
class D extends A {
public void speak(){
System.out.println("Class D");
}
}
List<A> as = new ArrayList<A>();
as.add(new A());
as.add(new B());
as.add(new D());
A a0 = as.get(0);
A a1 = as.get(1);
A a2 = as.get(2);
a0.speak(); // >> Class A
a1.speak(); // >> Class B
a2.speak(); // >> Class D
現在,在此示例中,單個集合中包含三個不同類的實例。 當您傳遞或修改此集合時,您將永遠不知道每個對象實際上是哪個類。 您所知道的都是它們都是A類型的,盡管實際上它們可以是A的任何子類型(例如B或D),但它們一定是該類型的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.