2010-06-24 7 views
13

Ya sea en C# o en Java o en cualquier otro idioma que siga los conceptos de Ups, generalmente tiene 'Objeto' como superclase para él de forma predeterminada. ¿Por qué necesitamos tener Object como clase base para todas las clases que creamos?¿Por qué necesitamos tener la clase Object como baseclass para todas las clases?

Cuando la herencia múltiple no es posible en un lenguaje como C# o Java, ¿cómo podemos derivar nuestra clase de otra clase cuando ya se deriva de la clase Object? Esta pregunta puede parecer tonta, pero quería saber algunas opiniones de expertos al respecto.

+3

¡Así que no necesitamos punteros vacíos! –

+1

¿por qué lidiar con un bosque si podemos lidiar con un árbol? – irreputable

Respuesta

14

Tener una jerarquía de tipos con un único enraizamiento puede ser útil de varias maneras. En particular, antes de que llegaran los genéricos, era la única forma en que algo como ArrayList funcionaría. Con los genéricos, hay una ventaja significativamente menor, aunque podría ser útil en algunas situaciones, sospecho. EDITAR: como ejemplo, el modelo de construcción LINQ to XML es muy "loose" en términos de ser especificado a través del object ... pero funciona muy bien.

En cuanto a los derivados de diferentes clases - se derivan directamente de una clase, pero que a su vez derivan indirectamente de otro, y así sucesivamente hasta el objeto.

Tenga en cuenta que las cosas que "todos los objetos tienen en común" como el código hash, la igualdad y los monitores cuentan como otra decisión de diseño que cuestionaría la sabiduría de. Sin una sola jerarquía enraizada, estas decisiones de diseño posiblemente no se habrían hecho de la misma manera;)

+0

Y para C# al menos hay boxeo: como todo se deriva del objeto, todo puede almacenarse en un objeto. Un poco mejor que el vacío * – simendsjo

+0

@simendsjo: Eso está cubierto principalmente en mi primer párrafo, ¿no? Es por eso que 'ArrayList' era factible. La pregunta es, con genéricos, ¿aún necesitarías Object para esto? –

+1

Para colecciones heterogéneas, sospecho. –

9

El hecho de que cada clase hereda un objeto garantizado por el compilador.
lo que significa que es usted escribir:

class A {} 

se compilará como:

class A : Object{} 

Pero si usted afirma:

class B : A {} 

Object habrá en la jerarquía de B pero no directamente - entonces todavía no hay herencia múltiple.

1

En cuanto a la primera parte de su pregunta, se trata de cómo las clases reciben propiedades y métodos comunes. También es así como podemos tener parámetros fuertemente tipados para funciones que pueden aceptar cualquier objeto.

En cuanto a su segunda pregunta, simplemente deriva su clase de la otra clase; entonces será un descendiente de esa clase, que a su vez es un descendiente de Object. No hay conflicto

1

Tiene la clase base Object porque entre otros porque la clase Object tiene métodos (como, en .NET, GetHashCode(), que contienen la funcionalidad común que debería tener cada objeto).

La herencia múltiple es, en efecto, no es posible, pero es posible derivar la clase A de la clase B, ya que A no puede derivar directamente de objetos, pero B hace, por lo que todas las clases en última instancia derivan del objeto, si vas lejos suficiente en la jerarquía de herencia de la clase.

3

En

1) La clase corta

objeto define el estado básico y el comportamiento que todos los objetos deben tener, tales como la capacidad de compararse con otro objeto, para convertir a una cadena, que esperar una condición variable , para notificar a otros objetos que una variable de condición ha cambiado, y para devolver la clase del objeto.

2) Puede tener B extienden C, y A se extienden B. A es la clase niño de B, y B es la clase hija de C. Naturalmente, A es también una clase de niño de C.

2

Bueno, la herencia múltiple de Object no se aplica; se puede considerar como:

"Si un tipo no tiene un tipo de base, entonces implícitamente inyecte Object".

Por lo tanto, al aplicar la regla ad-nauseam, todos los tipos heredan del objeto una sola vez, ya que en la parte inferior de la jerarquía debe ser un tipo que no tiene ninguna base; y por lo tanto, que heredará implícitamente del Object.

cuanto a por qué idiomas/marcos tienen esto como una característica, tengo un par de razones:

1) La idea de en el nombre de 'orientado a objetos'. Todo es un objeto, por lo tanto, todo debería tener 'Objeto' (o equivalente) en su núcleo, de lo contrario, el principio de diseño se rompería desde el principio.

2) Permite que el marco proporcione ganchos para las operaciones comunes que todos los tipos deberían/​​necesitarían soportar. Tales como la generación de hash de código, salida de cadena para la depuración, etc, etc

3) Significa que se puede evitar recurrir al tipo desagradable arroja que pueden romper cosas - como (((int *)(void*))value) - ya que tiene un supertipo amistosa agradable para todo

Probablemente haya mucho más que esto, y en el tiempo que me llevó escribir esto, se han publicado 6 nuevas respuestas; así que lo dejaré allí y espero que mejores personas de las que pueda explicar con más detalle y quizás mejor :)

+0

1) orientado a objetos aún funciona cuando no está enraizado solo. 2) las características podrían ser proporcionadas por el lenguaje en lugar de un solo objeto raíz de la biblioteca. 3) podría mejorar algunos diseños _no_ permitir un "tipo súper amigable para" _todo_ – nicerobot

+0

@nicerobot: 1) Nunca dije que la herencia múltiple viola OO. Dije que una plataforma que los pupports sean OO puros debería tener un supertipo Object. Tener más de un supertipo raíz es completamente válido. 2) Por supuesto que pueden ser proporcionados por el idioma. Una vez más, nunca dije que no pudieran (¿a quién le importa de dónde viene la funcionalidad?). En el caso de .Net y Java, sin embargo, * están * implementados por el supertipo, lo que también significa que los compiladores tienen menos trabajo por hacer. 3) Tal vez sea así - ¿pero entonces probablemente no tendrías un ambiente de OO puro? –

+1

@ andras-zoltan No te estaba atacando, pero solo estaba explicando las posibilidades. En cuanto a "OO puro", solo estaba diciendo que no requiere un supertipo común para seguir siendo OO puro y eso no implica el apoyo a la herencia múltiple. Por ejemplo, en mi lenguaje sin raíz, 'clase A {}' y 'clase B {}' no tienen un antecesor común, pero el lenguaje todavía puede imponer objetos como únicos tipos. Podría, por ejemplo, implementar 'clase Number {}' y 'clase Integer: Number {}' que no tienen relación jerárquica con 'clase String {}' y todavía soy un entorno puramente OO. – nicerobot

1

Solo para comparar, echemos un vistazo a un lenguaje que no impone una sola clase raíz - Objetivo -DO. En la mayoría de los entornos de Objective-C habrá tres clases de raíz disponibles (Object, NSObject y NSProxy), y puede escribir su propia clase de raíz simplemente no declarando una superclase. De hecho, Object está en desuso y solo existe por razones heredadas, pero es informativo incluirlo en esta discusión. El lenguaje está escrito en pato, por lo que puede declarar el tipo de una variable como "cualquier objeto antiguo" (escrito como id), entonces ni siquiera importa qué clase de raíz tiene.

Bien, entonces tenemos todas estas clases base. De hecho, incluso para que el compilador y las bibliotecas de tiempo de ejecución puedan llegar a algún lugar, necesitan un comportamiento común: las clases raíz deben tener un puntero ivar llamado isa que haga referencia a una estructura de definición de clase. Sin ese puntero, el compilador no sabe cómo crear una estructura de objeto, y la biblioteca de tiempo de ejecución no sabrá cómo averiguar qué clase es un objeto, cuáles son sus variables de instancia, a qué mensajes responde y demás.

Así, aunque Objective-C afirma tener múltiples clases de raíz, de hecho hay un comportamiento que deben implementar todos los objetos. Entonces, en todo menos en el nombre, existe realmente una superclase primitiva común, aunque una con menos API que java.lang.Object.

N.B. como ocurre, tanto NSObject como NSProxy proporcionan una API enriquecida similar a java.lang.Object, a través de un protocolo (como una interfaz Java). La mayoría de las API que afirman tratar con el tipo id (recuerde, ese es el tipo de "cualquier objeto antiguo") realmente asumirá que responde a los mensajes en el protocolo. Para cuando necesite usar un objeto, en lugar de simplemente crearlo con un compilador, resulta útil doblar todo este comportamiento común como igualdad, hashing, descripciones de cadenas, etc. en la clase raíz.

1

Bien herencia múltiple es un juego de pelota totalmente diferente.

Un ejemplo de herencia múltiple: -

class Root 
{ 
public abstract void Test(); 
} 

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

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

class leafChild : rightChild, leftChild 
{ 
} 

El problema aquí es leafChild hereda Prueba de rightChild y leftChild. Entonces, un caso de métodos contradictorios. Esto se llama un problema de diamantes.

Pero cuando se utiliza el objeto como superclase la jerarquía dice así: -

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

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

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

Así que aquí se derivan dos clases de objetos, pero ese es el final de la misma.

1

Actúa como una plantilla para todos los objetos que se derivarán de ella, de modo que se proporciona por defecto una funcionalidad común requerida por cada objeto. Por ejemplo, clonación, código hash y bloqueo de objetos, etc.

Cuestiones relacionadas