簡體   English   中英

為什么我們需要將Object類作為所有類的基類?

[英]Why do we need to have Object class as baseclass for all the classes?

無論是在C#還是Java中,還是在oops概念之后的任何其他語言中,默認情況下概念都將“Object”作為超類。 為什么我們需要將Object作為我們創建的所有類的基類?

當在C#或Java等語言中無法進行多重繼承時,如果已經從Object類派生,我們如何從另一個類派生我們的類。 這個問題可能看起來很傻,但想知道一些專家的意見。

具有單根類型的層次結構可以以各種方式方便。 特別是在仿制葯出現之前,這是像ArrayList這樣的東西的唯一方法。 有了泛型,它的優勢明顯減少 - 雖然它在某些情況下仍然有用,但我懷疑。 編輯:作為一個例子,LINQ to XML的構造模型在通過object指定方面非常“松散”......但它的效果非常好。

至於派生自不同的類 - 你直接從一個類派生,但這又將從另一個類間接派生,依此類推到Object。

請注意,“所有對象具有共同點”的東西,例如哈希碼,相等性和監視器,都算作另一個設計決策,我會質疑它的智慧。 如果沒有單一的根系層次結構,這些設計決策可能不會以同樣的方式進行;)

事實上每個類都繼承了編譯器確保的對象。
意思是你寫的:

class A {}

它將編譯如下:

class A : Object{}

但如果你說:

class B : A {}

Object將在B的層次結構中但不是直接 - 因此仍然沒有多重繼承。

簡而言之

1)Object類定義所有對象必須具有的基本狀態和行為,例如將自己與另一個對象進行比較,轉換為字符串,等待條件變量,通知其他對象條件變量具有的能力改變了,並返回對象的類。

2)你可以有B擴展C和A擴展B. A是B的子類,B是C的子類。當然,A也是C的子類。

好吧, Object的多重繼承不適用 - 您可以將其視為:

“如果類型沒有基類型,則隱式注入Object ”。

因此,應用規則ad-nauseam,所有類型只從對象繼承一次 - 因為在層次結構的底部必須是沒有基礎的類型; 因此它將隱式地從Object繼承。

至於為什么這些語言/框架將此作為一項功能,我有幾個原因:

1)“面向對象”這個名稱的線索。 一切都是一個對象,因此一切都應該有'對象'(或等效的)在它的核心,否則設計原則將從一開始就被打破。

2)允許框架為所有類型應該/可能需要支持的常見操作提供掛鈎。 如哈希碼生成,調試字符串輸出等。

3)這意味着你可以避免使用可以破壞東西的令人討厭的類型轉換 - 比如(((int *)(void*))value) - 因為你有一個很好的友好超類型的一切

可能還有比這更多的東西 - 在我寫這篇文章的時候已經發布了6個新的答案; 所以我會留在那里,希望比我更好的人能夠更詳細地解釋,也許更好:)

關於問題的第一部分,它是類如何獲得公共屬性和方法。 這也是我們如何為可以接受任何對象的函數提供強類型參數。

關於你的第二個問題,你只需從另一個班級中派出你的班級; 然后它將成為該類的后代,而后者又是Object的后代。 沒有沖突。

你有Object基類,因為Object類有方法(比如在.NET中, GetHashCode() ,它包含每個對象應該具有的通用功能)。

多重繼承確實是不可能的,但是可以從類B派生出類A,因為A可能不是直接派生自Object,而是B,所以所有類最終都是從Object派生的,如果你在類的繼承中走得足夠遠層次結構。

為了比較,我們來看一下不強制執行單個根類的語言 - Objective-C。 在大多數Objective-C環境中,將有三個可用的根類( ObjectNSObjectNSProxy ),您可以通過不聲明超類來編寫自己的根類。 事實上, Object已被棄用,並且僅出於遺留原因而存在,但在此討論中包含它是有用的。 該語言是鴨子類型,因此您可以將變量的類型聲明為“任何舊對象”(寫為id ),然后它甚至不管它具有什么根類。

好的,所以我們已經擁有了所有這些基類。 事實上,即使編譯器和運行時庫能夠到達任何地方,他們也需要一些常見的行為:根類必須都有一個名為isa的指針ivar,它引用一個類定義結構。 沒有該指針,編譯器不知道如何創建對象結構,並且運行時庫將不知道如何找出對象是什么類,它的實例變量是什么,它響應什么消息等等。

因此,盡管Objective-C聲稱有多個根類,但事實上所有對象都必須實現一些行為。 所以除了名稱以外,其他所有的超級類都是如此,盡管API比java.lang.Object少。

請注意, NSObjectNSProxy都通過協議(如Java接口)提供類似於java.lang.Object的豐富API。 聲稱處理id類型的大多數API(請記住,這是“任何舊對象”類型)實際上會假設它響應協議中的消息。 當你真正需要使用一個對象時,而不是僅僅使用編譯器創建它,結果將所有這些常見行為(如相等,散列,字符串描述等)折疊到根類中是有用的。

多重繼承是一個完全不同的球賽。

多重繼承的一個例子: -

class Root
{
public abstract void Test();
}

class leftChild : Root
{
public override void Test()
{
}
}

class rightChild : Root
{
public override void Test()
{
}
}

class leafChild : rightChild, leftChild
{
}

這里的問題是leafChild繼承了rightChild和leftChild的測試。 所以一個沖突的方法的情況。 這被稱為鑽石問題。

但是,當您將對象用作超類時,層次結構如下所示: -

class Object
    {
        public abstract void hashcode();
        //other methods
     }

    class leftChild : Object
    {
    public override void hashcode()
    {
    }
    }

    class rightChild : Object
    {
    public override void hashcode()
    {
    }
    }

所以這里我們從Object派生這兩個類,但這就是它的結束。

它就像一個模板,用於從中派生出來的所有對象,因此默認情況下會提供每個對象所需的一些常用功能。 例如克隆,哈希碼和對象鎖定等。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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