簡體   English   中英

Java。 類的類型與對象

[英]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中定義的方法,因為編譯器僅知道xRectangle或某些子類。 如果在Square聲明一個新方法,則不能在上面的調用中使用它。

但是,如果x仍然是對Square的引用,那么當您調用Rectangle定義的方法時,該程序實際上將運行您為Square編寫的方法(如果已覆蓋Rectangle )。

也許這個例子會有所幫助。 假設Rectangle聲明了public方法aaabbb 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM