una sintaxis simple resueltos polimorfismo herencia ejercicios ejemplos definicion con java inheritance constructor

sintaxis - Herencia de Constructor de Java



polimorfismo en java (10)

Me preguntaba por qué en Java los constructores no son heredados. Sabes cuando tienes una clase como esta:

public class Super { public Super(ServiceA serviceA, ServiceB serviceB, ServiceC serviceC){ this.serviceA = serviceA; //etc } }

Más tarde, cuando heredes de Super , java se quejará de que no hay un constructor predeterminado definido. La solución es obviamente algo así como:

public class Son extends Super{ public Son(ServiceA serviceA, ServiceB serviceB, ServiceC serviceC){ super(serviceA,serviceB,serviceC); } }

Este código es repetitivo, no SECO e inútil (en mi humilde opinión) ... así que trae la pregunta de nuevo:

¿Por qué java no es compatible con la herencia del constructor? ¿Hay algún beneficio en no permitir esta herencia?


Básicamente heredas los constructores en el sentido de que simplemente puedes llamar a super si y cuando sea apropiado, es solo que sería propenso a errores por razones que otros han mencionado si ocurriera de manera predeterminada. El compilador no puede suponer cuándo es apropiado y cuándo no.

El trabajo del compilador es proporcionar la mayor flexibilidad posible a la vez que se reduce la complejidad y el riesgo de efectos secundarios no deseados.


Cuando heredas de Super esto es lo que en realidad sucede:

public class Son extends Super{ // If you dont declare a constructor of any type, adefault one will appear. public Son(){ // If you dont call any other constructor in the first line a call to super() will be placed instead. super(); } }

Entonces, esa es la razón, porque tienes que llamar a tu constructor único, ya que "Super" no tiene uno predeterminado.

Ahora, tratando de adivinar por qué Java no admite la herencia del constructor, probablemente porque un constructor solo tiene sentido si se trata de instancias concretas, y no debería poder crear una instancia de algo cuando no se sabe cómo se define (por polimorfismo).


Debido a que construir su objeto de subclase se puede hacer de una manera diferente a como se construye su superclase. Puede que no desee que los clientes de la subclase puedan llamar a ciertos constructores disponibles en la superclase.

Un ejemplo tonto:

class Super { protected final Number value; public Super(Number value){ this.value = value; } } class Sub { public Sub(){ super(Integer.valueOf(0)); } void doSomeStuff(){ // We know this.value is an Integer, so it''s safe to cast. doSomethingWithAnInteger((Integer)this.value); } } // Client code: Sub s = new Sub(Long.valueOf(666L)): // Devilish invocation of Super constructor! s.doSomeStuff(); // throws ClassCastException

O incluso más simple:

class Super { private final String msg; Super(String msg){ if (msg == null) throw new NullPointerException(); this.msg = msg; } } class Sub { private final String detail; Sub(String msg, String detail){ super(msg); if (detail == null) throw new NullPointerException(); this.detail = detail; } void print(){ // detail is never null, so this method won''t fail System.out.println(detail.concat(": ").concat(msg)); } } // Client code: Sub s = new Sub("message"); // Calling Super constructor - detail is never initialized! s.print(); // throws NullPointerException

A partir de este ejemplo, verá que necesitaría alguna forma de declarar que "Quiero heredar estos constructores" o "Quiero heredar todos los constructores excepto estos", y luego también debería especificar una herencia de constructor predeterminada Preferencia solo en caso de que alguien agregue un nuevo constructor en la superclase ... o simplemente podría requerir que repita los constructores de la superclase si desea "heredarlos", lo que podría decirse que es la forma más obvia de hacerlo.


Debido a que los constructores son un detalle de implementación, no son algo que un usuario de una interfaz / superclase pueda invocar en absoluto. Para cuando obtienen una instancia, ya está construida; y viceversa, en el momento en que construyes un objeto, por definición, no hay ninguna variable asignada actualmente.

Piensa en lo que significaría forzar a todas las subclases a tener un constructor heredado. Yo sostengo que es más claro pasar las variables directamente que para la clase para "mágicamente" tener un constructor con cierto número de argumentos solo porque es padre.


La respuesta de David es correcta. Me gustaría añadir que podría estar obteniendo un signo de Dios de que su diseño está en mal estado, y que "Hijo" no debería ser una subclase de "Super", sino que, en cambio, Super tiene algunos detalles de implementación mejor expresados al tener la funcionalidad que proporciona Son, como una especie de estrategia.

EDITAR: La respuesta de Jon Skeet es asombrosa.


Los constructores no son polimórficos.
Al tratar con clases ya construidas, podría tratar con el tipo declarado del objeto o cualquiera de sus subclases. Para eso es útil la herencia.
Los constructores siempre son llamados en el tipo específico, por ejemplo, new String() . Las subclases hipotéticas no tienen ningún papel en esto.


No conozco ningún idioma en el que las subclases hereden constructores (pero entonces, no soy una gran poliglotante de programación).

Here''s una discusión sobre la misma pregunta sobre C #. El consenso general parece ser que complicaría el lenguaje, introduciría el potencial de efectos secundarios desagradables a los cambios en una clase base y, en general, no debería ser necesario en un buen diseño.


Porque una (súper) clase debe tener control total sobre cómo se construye. Si el programador decide que no tiene sentido proporcionar un constructor predeterminado (sin argumentos) como parte del contrato de la clase, entonces el compilador no debe proporcionar uno.


Supongamos que los constructores fueron heredados ... entonces porque cada clase eventualmente deriva de Object, cada clase terminaría con un constructor sin parámetros. Esa es una mala idea ¿Qué esperas exactamente?

FileInputStream stream = new FileInputStream();

¿que hacer?

Ahora, potencialmente, debería haber una manera de crear fácilmente los constructores de "paso a través" que son bastante comunes, pero no creo que deba ser el predeterminado. Los parámetros necesarios para construir una subclase a menudo son diferentes de los requeridos por la superclase.


Una clase derivada no es la misma clase que su clase base y es posible que le importe o no que los miembros de la clase base se inicialicen en el momento de la construcción de la clase derivada. Esa es una determinación hecha por el programador, no por el compilador.