假設你有一個Shape
基類和各種派生類型:Circle
等上溯造型使得當對象
是否有過任何理由做一個新的對象時,通過寫這上溯造型在那裏:
Shape s = new Circle();
,而不是這樣的:
Circle s = new Circle();
,並由各這兩個語句所做的s
對象以任何方式從各個不同的其他?
假設你有一個Shape
基類和各種派生類型:Circle
等上溯造型使得當對象
是否有過任何理由做一個新的對象時,通過寫這上溯造型在那裏:
Shape s = new Circle();
,而不是這樣的:
Circle s = new Circle();
,並由各這兩個語句所做的s
對象以任何方式從各個不同的其他?
就JVM而言,這兩個語句將產生相同的對象。顯示您只打算將該對象用於基類或接口並不罕見。例如。這是常見的:
List<String> list = new ArrayList<String>();
雖然一般不是一個好主意,你可以施放Shape
回爲Circle
,如果你肯定知道,這是一個,例如與Shape s
你可以把它帶回一個Circle c
有:
if (s instanceof Circle) {
Circle c = (Circle) s;
// handle Circle case
}
沒有,對象本身沒有什麼兩樣。只有編譯器認爲他看到的是不同的(例如,哪些方法可用)。
這樣做一個演員的一個原因是表達你喜歡如何對待對象(以便您可以輕鬆插入不同的派生類)。
Circle s = new Circle();
這裏的對象是指類Cricle
Shape s = new Circle(); 這裏它的對象是指接口
兩者都是一樣的。
我同意@ WhiteFang34說的。
看到這個Coding to interfaces? 這可能對你有幫助。
即使Shape可能是一個抽象的或者甚至是一個具體的基類,你也可以爭辯說,你的第一個例子(即Shape s = new Circle();
)與「編碼到接口」可以有相同的優點。例如,如果您只使用Shape上定義的方法而不是Circle中特定的方法,那麼只需更改一行代碼(例如Shape s = new Square();
),就可以輕鬆地將您正在使用的實現更改爲Square。
對象在你的兩個例子中都是一樣的,第一個選項可以被認爲更好的原因更多的是風格的東西。編碼到接口可以使代碼庫更容易擴展和修改。
實例化的對象完全相同。
一個向上轉型的後果是:
在回答你的問題時,兩個對象是完全相同的。這兩個引用可以在同一個對象指向:
Circle c = new Circle();
Shape s = c;
編碼,接口可以讓你改變實現類與您的代碼的影響降到最低。假設你有這樣的:
Set<String> names = new HashSet<String>(); // using Set reference not HashSet
names.add("Frank");
names.add("John");
names.add("Larry");
for(String name: names) {
System.out.println(name + " is in the team");
}
現在你的需求的變化,你想按字母順序,即用它代替TreeSet的HashSet的要打印的名稱。因爲你已編碼的接口,而不是使用特定於HashSet的類中的任何方法,你只需要改變一個行:
Set<String> names = new TreeSet<String>(); // the only line of code that changes
names.add("Frank");
names.add("John");
names.add("Larry");
for(String name: names) {
System.out.println(name + " is in the team");
}
接口還可以讓你使用依賴注入。它允許您使用編寫代碼時可能不存在的類。