2010-06-24 67 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

它的作用类似于所有从它派生的对象的模板,因此默认情况下会提供每个对象所需的一些常用功能。例如克隆,哈希码和对象锁等。

相关问题