[英]Java. Type vs Object of a class
例如,當我有一個Rectangle類和一個Square類時。 如果Square類擴展Rectangle,則Square類是Rectangle類的子類。 現在說我有代碼。 Rectangle shape = new Square(5,6);
我將創建一個對象,但是它將是Rectangle類型,但是使用square的構造函數還是Square的對象?,我的困惑始於類Square,它具有與Rectangle類相同的方法,但是它將使用類中的方法方形不類矩形。 那么我是否創建了Square對象,但是具有Rectangle類型?
評論:每個人都知道正方形不會擴展矩形,這讓每個人都感到憤怒,但這是我的老師的例子,純粹顯示了繼承性,實際上他在演示如何使用此代碼如何創建錯誤。
這使很多人感到困惑。 讓我嘗試將其分解。
當您說new Square
,將使用Square
構造函數創建對象。 該對象在其整個存在期間將具有Square
類型。
當聲明類型為Rectangle
的變量時,即Rectangle x;
或Rectangle x = (anything);
您告訴編譯器x
(當它不為null時)將始終是對Rectangle
或其任何子類 (包括Square
)的引用。 當您說Rectangle x = new Square(...)
, x
將是對Square
的引用,即Rectangle
。 但是 ,以后可以將x
重新分配為其他不是Square
Rectangle
。
這意味着,當您說x.method(...)
,編譯器僅允許您使用Rectangle
中定義的方法,因為編譯器僅知道x
是Rectangle
或某些子類。 如果在Square
聲明一個新方法,則不能在上面的調用中使用它。
但是,如果x
仍然是對Square
的引用,那么當您調用Rectangle
定義的方法時,該程序實際上將運行您為Square
編寫的方法(如果已覆蓋Rectangle
)。
也許這個例子會有所幫助。 假設Rectangle
聲明了public
方法aaa
和bbb
。 在Square
,您編寫了重寫方法aaa
,沒有重寫bbb
,而是聲明了一個新的公共方法ccc
。
Rectangle x = new Square(10);
Rectangle y = new Rectangle(5,6);
// assume that x and y aren't changed
x.aaa(); // runs the overriding method aaa in Square
y.aaa(); // runs the method aaa in Rectangle
x.bbb(); // runs the method in Rectangle, since it's not overridden. But
// if bbb calls aaa, then it will call the aaa in Square.
y.bbb(); // runs the method in Rectangle
x.ccc(); // illegal. Even though the object is actually a Square, the
// compiler isn't allowed to know that.
y.ccc(); // illegal
((Square)x).ccc(); // This is how you can get to the new method that you
// declared in Square. Even though the compiler doesn't know
// that x is a Square, when you use the cast, you tell the
// compiler that it's OK fo treat it as a Square, and to access
// the method defined only in Square.
((Square)y).ccc(); // Will throw ClassCastException at runtime, because
// y isn't a Square.
希望這可以幫助。
您創建了一個Square類型的對象。
對new Foo(...)
調用將始終創建Foo,沒有例外。 而且它將始終再次調用Foo
的構造函數,而不會出現異常。 也就是說,如果Foo從另一個類擴展,那么Foo的構造函數要做的第一件事就是調用超類的構造函數。 再說一次,這也沒有例外-盡管您不一定會在代碼中看到它,因為如果您沒有對super(...)
的調用,並且在super中存在無參數的構造函數類,則編譯器將自動為您調用該構造函數。 但是,無論哪種方式,它總是會被調用。
由於已將Square設置為一個矩形,因此該對象也是Rectangle的實例。 在您的課程中,正方形始終是矩形,但並非所有矩形都是正方形。
Rectangle shape
僅表示,據編譯器所知,它“至少”是Rectangle。 它可能完全是一個Rectangle,也可能是Rectangle的子類(例如Square),但不會是Number。
例如,當您調用shape.getArea()
,JVM將查找shape
的實際類型(不僅是其編譯時類型,而且還包括您在調用new
時實際創建的類型),並調用該方法。該類定義。
繼承總是給您的對象一個is-a關系 。 因此,憑借Square
擴展的Rectangle
,可以肯定地說Square
是 Rectangle
。
您已經創建了Square
的實例,但是您將只能在其實例上使用其父Rectangle
提供的方法。
您在尋找的答案是“ Square真的是矩形嗎?”。 從寶石學的角度來看,答案是肯定的,但從軟件的角度來看,答案可能並不那么明顯。 “是”關系必須遵循Liskov替代原則 。
因此,基本上,如果基類具有某些不適用於派生類的方法,則它不是“ is-a”關系。
例如
矩形類{
/ 構造函數代碼 /
public void changeWidth(){....} public void changeLength(){....}
}
changeWidth和changeLength是兩個函數,它們對於矩形(而不是正方形)非常有意義,因為所有邊都相等。 盡管從我的角度來看,盡管您可以在平方類中破解並給出自己的兩個函數的實現,但是關系看起來並不自然。
至於其他答案,我也同意。
那就是所謂的多態性,做功課。 shape變量僅是參考,而實際對象是Square對象。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.