2010-06-24 40 views
13

無論是在C#或Java或任何其他遵循oops概念的語言中,默認情況下,它的Object都是超類。爲什麼我們需要將Object作爲我們創建的所有類的基類?爲什麼我們需要將Object類作爲所有類的基類?

如果在諸如C#或Java的語言中無法實現多繼承,那麼當它已經從Object類派生時,我們如何從另一個類派生我們的類。這個問題可能看起來很愚蠢,但想知道一些專家對此的看法。

+3

所以我們不需要void指針! – 2010-06-24 10:09:39

+1

如果我們能處理一棵樹,爲什麼要處理森林? – irreputable 2010-09-23 17:47:36

回答

14

具有單根類型層次結構可以以各種方式得心應手。特別是在仿製藥出現之前,這是類似ArrayList這樣的工作的唯一途徑。有了泛型,它的優勢顯着減少 - 儘管它在某些情況下仍然有用,但我懷疑。編輯:作爲一個例子,LINQ to XML的構建模型在通過object指定的方面非常「鬆散」......但它工作得很好。

對於不同類派生 - 你得到直接從一類,但反過來這將衍生從另一個間接,並依此類推,直到對象。

請注意,「所有對象有共同點」的東西,比如散列碼,相等和監視器都算作另一個設計決定,我會質疑它的智慧。如果沒有單一的根層次,這些設計決策可能不會以相同的方式進行;)

+0

而對於c#至少有拳擊 - 因爲所有東西都來自對象,所有東西都可以存儲在一個對象中。比void更好一點* – simendsjo 2010-06-24 09:36:53

+0

@simendsjo:這大部分都在我的第一段中,不是嗎?這就是爲什麼'ArrayList'是可行的。問題是,對於泛型,你是否還需要Object? – 2010-06-24 09:40:39

+1

對於異構集合,我懷疑。 – 2010-06-24 09:49:01

9

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

class A {} 

它將編譯像:

class A : Object{} 

但是,如果你的狀態:

class B : A {} 

Object將在直接B而不是層級 - 所以仍然沒有多重繼承。

1

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

關於你的第二個問題,你只需從另一個類派生你的類;它將成爲該類的後代,而後者又是對象的後代。沒有衝突。

1

你有對象的基類,因爲除其他外,因爲Object類中有一些方法(比如,在.NET中,GetHashCode(),其中包含常用功能對象應該有)。

多重繼承確實是不可能的,但也可以從B類派生類A,因爲A可能無法直接從Object派生,而B呢,因此所有的類最終從Object派生,如果你走得很遠足夠在班級的繼承層次中。

3

總之

1)對象類定義的基本狀態和行爲,所有對象必須有,如對自己比較另一目的,以轉換爲字符串,能夠將等待條件可變,通知其他對象一個條件變量已經改變,並返回對象的類。

2)可以具有乙延伸C,和A延伸B. A是子類B的,B是子類C.自然的,A也是一個子類C.

2

的那麼,Object的多重繼承不適用 - 您可以將它想象爲:

「如果某個類型沒有基本類型,則隱式注入Object」。因此,應用規則ad-nauseam,所有類型只從一個對象繼承一次 - 因爲在層次結構的底部必須是一個沒有基礎的類型;因此它將隱含地從Object繼承。

至於爲什麼這些語言/框架有這樣一個特點,我有幾個方面的原因:

1)的線索是在名稱爲「面向對象」。一切都是一個對象,因此一切都應該具有「對象」(或等價物)的核心,否則設計原則將從一開始就被打破。

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

3)這意味着你能避免訴諸討厭的類型強制轉換,可以打破的東西 - 像(((int *)(void*))value) - 因爲你的一切

一個不錯的友好超

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

+0

1)面向對象仍然工作時,不單根紮根。 2)可以通過語言來提供特徵,而不是庫的單個根對象。 3)它可能會改進一些設計_不允許「友好的超類型」_everything_ – nicerobot 2010-06-24 11:05:06

+0

@nicerobot:1)我從來沒有說過多繼承違反OO。我說一個支持純OO的平臺應該有一個Object超類型。擁有多個超級超類型是完全有效的。 2)當然,他們可以由語言提供 - 我再也沒有說過他們不能(誰關心功能來自哪裏?)。然而,在.Net和Java的情況下,它們*是由超類型實現的,這也意味着編譯器的工作量較少。 3)也許是這樣 - 但你可能不會有一個純粹的面向對象的環境? – 2010-06-24 11:39:19

+1

@ andras-zoltan我不是在攻擊你,而是在闡述可能性。至於「純粹的面向對象」,我只是說它不需要共同的超類型,仍然是純粹的面向對象,並不意味着支持多重繼承。例如,在我的無根語言中,'class A {}'和'class B {}'沒有共同的祖先,但是語言仍然可以強制對象作爲唯一的類型。例如,我可以實現'class Number {}'和'class Integer:Number {}',它們與'class String {}'沒有層次關係,我仍然是一個純粹的面向對象的環境。 – nicerobot 2010-06-24 13:09:33

1

只是爲了比較,讓我們來看看不強制單個根類的語言 - 目標-C。在大多數Objective-C環境中,將有三個根類可用(Object,NSObjectNSProxy),並且您可以通過不聲明超類來編寫自己的根類。實際上,Object已被棄用,並且僅出於傳統原因存在,但在本討論中包含它是有益的。該語言是duck typed的,所以你可以聲明一個變量的類型爲「任何舊對象」(寫作id),那麼它甚至不管它有什麼根類。

好的,所以我們已經有了所有這些基類。事實上,即使編譯器和運行時庫能夠到達任何地方,它們也需要一些常見的行爲:根類必須都有一個名爲isa的指針,它引用了一個類定義結構。沒有這個指針,編譯器不知道如何創建一個對象結構,運行時庫不知道如何找出對象是什麼類,它的實例變量是什麼,它響應什麼消息等等。因此即使Objective-C聲稱擁有多個根類,實際上也有一些行爲必須實現對象必須實現的一些行爲。所以除了名字之外,還有一個非常普通的原始超類,儘管API比java.lang.Object少。

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

1

多繼承是一個完全不同的球類遊戲。

多重繼承的例子: -

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派生兩類但這是它的結束。

1

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

相關問題