2009-03-06 20 views
13

permite echar un ejemplo en C#Constructores y herencia

public class Foo 
{ 
    public Foo() { } 
    public Foo(int j) { } 
} 

public class Bar : Foo 
{ 

} 

Ahora, todos los miembros públicos de Foo es accesible en Bar excepto el constructor. no puedo hacer algo como

Bar bb = new Bar(1); 

Por qué los constructores no son heredables?

ACTUALIZACIÓN

entiendo que podamos constructores de cadena, pero me gustaría saber por qué la construcción anterior no es válido. Estoy seguro de que debería haber una razón válida para ello.

+0

duplicado de http://stackoverflow.com/questions/426484/why-are-constructors-not-inherited –

Respuesta

14

Los constructores no son heredables porque pueden causar un comportamiento extraño y no deseado. Más específicamente, si agregó un nuevo constructor a una clase base, todas las clases derivadas obtienen una instancia de ese constructor. Eso es algo malo en algunos casos, porque tal vez su clase base especifique parámetros que no tienen sentido para sus clases derivadas.

Un ejemplo común para esto es que en muchos idiomas, la clase base para todos los objetos (comúnmente llamada "Objeto") tiene un constructor sin parámetros. Si los constructores se heredaran, esto significaría que todos los objetos tienen un constructor sin parámetros, y no hay forma de decir "Quiero que las personas que hacen una instancia de esta clase proporcionen los parámetros X, Y y Z; de lo contrario, su código no debería compilarse". " Para muchas clases, es importante definir ciertos parámetros para su función adecuada, y hacer que los constructores no sean heredables es parte de la forma en que los autores de la clase pueden garantizar que siempre se definan algunos parámetros.

Editar para responder a los comentarios: Ramesh señala que si los constructores se heredaran como él quisiera, siempre podría anular los constructores de la clase base utilizando constructores declarados de forma privada en cada clase derivada. Eso es cierto, pero hay un problema logístico con esta estrategia. Requiere que los escritores de las clases derivadas tengan que mirar de cerca las clases base y agregar un constructor privado si desean la herencia de bloques del constructor de la clase base. No solo es mucho trabajo para las personas que escriben clases derivadas, este tipo de dependencia implícita en todas las clases es exactamente el tipo de cosa que puede causar un comportamiento extraño.

Ramesh - no es que lo que describes sea imposible de agregar a un idioma. En general, no se hace porque ese tipo de comportamiento podría confundir a las personas y llevar a una gran cantidad de depuración y escritura de código.

Quintin Robinson brinda algunas respuestas muy útiles a esta pregunta en los comentarios que definitivamente vale la pena leer.

+0

Si agrega un constructor a la clase base, podría inicializar las cosas presente solo en esa clase y eso es un buen comportamiento, no veo por qué dices que es algo malo. – Ramesh

+0

Porque puede * requerir * que se inicialicen miembros que no sean de base en su clase derivada. –

+0

@Simon - Si es así, siempre puedo anular mis constructores como funciones – Ramesh

7

Ellos son (a través de encadenamiento), que tendría que el constructor de la cadena en su objeto derivado .. IE:

public class Foo 
{ 
    public Foo() { } 
    public Foo(int j) { } 
} 

public class Bar : Foo 
{ 
    public Bar() : base() { } 
    public Bar(int j) : base(j) { } 
} 

Los constructores de los objetos derivados A continuación, encadenar las llamadas hacen los constructores en la base objetos.

This article proporciona algunos ejemplos más si desea obtener más información.

+0

Entiendo el encadenamiento, pero por qué mi ejemplo no es válido es lo que me gustaría entender (tengo actualicé la pregunta para resaltar lo mismo) – Ramesh

+0

Veo, lo siento por responder a una pregunta que no hizo Creo que leo un poco demasiado lejos. –

+0

Gracias Quintin, sus preguntas me hicieron pensar. +1 para una de sus respuestas para otra pregunta. – Ramesh

0

Creo que se puede hacer lo siguiente:

public class Bar : Foo 
{ 
    public Bar (int i) 
    : base (i) 
    { 
    } 
} 

que puede ser un poco - pero es la idea general.

+0

Entiendo el encadenamiento, pero por qué mi ejemplo no es válido es lo que me gustaría entender (he actualizado la pregunta para resaltarla) – Ramesh

1

Los constructores no son heredables por motivos de diseño. (Tenga en cuenta que esta es la misma situación en todos los lenguajes orientados a objetos que conozco). La respuesta simple es que en muchos casos no querrá que estén disponibles los mismos constructores que la clase base. Ver this SO thread para algunas explicaciones más completas.

0

La respuesta simple es que el lenguaje no funciona de esa manera.

La verdadera pregunta que está preguntando es por qué no funciona de esa manera :-) Bueno, es una elección arbitraria, y sigue desde C++ y Java (y muy posiblemente muchos otros lenguajes que influyeron en C#) .

La razón probable es que el compilador solo generará un constructor que no toma argumentos y simplemente llama al padre si quiere más de lo que el compilador le hace a usted mismo. Esta es la mejor opción ya que lo más probable es que hagas más que suplir al constructor padre.

2

Una razón por la que podría introducir un constructor en una clase es porque no tiene sentido tener una instancia de esa clase sin una "dependencia" específica. Por ejemplo, podría ser una clase de acceso a datos que tiene que tener una conexión a una base de datos:

public class FooRepository 
{ 
    public FooRepository(IDbConnection connection) { ... } 
} 

Si todos los constructores públicos de clases base estaban disponibles, a continuación, un usuario de la clase repositorio sería capaz de usar constructor por defecto de System.Object para crear una instancia de la clase no válida:

var badRepository = new FooRepository(); 

Ocultación constructores heredados por defecto significa que puede cumplir dependencias sin la preocupación de los usuarios que crean instancias "no válidos".

+0

+1 - Entiendo que los métodos no tienen la necesidad de ocultarse, pero el constructor debe ser por razones de inicialización. – Ramesh

2

El constructor Foo sólo puede conocer cómo inicializar un objeto Foo, por lo que no tiene sentido que también debe saber cómo inicializar cualquier subclase potencial

public class Bar : Foo 
{ 
public Bar(int i) : base(i) { } 
} 

La historia del constructor dice es: "Oye base de clase, por favor haz lo que tengas que hacer para estar en un buen estado, así puedo continuar y establecerme correctamente ".

2

Supongamos que los constructores son heredables. ¿Cómo podría deshabilitar los constructores heredados en muchos casos si no tienen sentido para una subclase?

En lugar de complicar el lenguaje con un mecanismo para bloquear la herencia, los diseñadores del lenguaje optaron por simplemente hacer constructores no heredables.

+0

+1 - Una de las respuestas precisas – Ramesh

+0

¿Qué le parece proporcionar que si una subclase contiene constructores, entonces no se heredan los constructores padre, sino que todos son (lo que significa que los constructores se generarán automáticamente a los constructores de cadena a matriz con correspondencia firmas)? Cualquier clase que no quiera "heredar" todos los constructores de sus padres debería proporcionar al menos uno propio. Si el padre no tiene un constructor sin parámetros, no habría otro significado lógico para una clase sin constructores. – supercat

0

Realmente, es porque el constructor padre no inicializaría completamente el objeto secundario.Un constructor es una especie de cosa personal en ese sentido. Es por eso que la mayoría de los idiomas no heredan constructores.