2011-01-25 17 views
32

? No es posible crear un objeto llamando directamente al constructor de una clase abstract. El constructor de una clase abstract solo puede invocarse desde una clase derivada. Por lo tanto, parece que los constructores de una clase abstracta deben ser protected o paquete-privado (este último para los casos inusuales de restringir el uso de un constructor a clases derivadas dentro del paquete). Sin embargo, Java permite que el constructor de una clase abstract sea public.¿Hay buenas razones para un constructor público de una clase abstracta

¿Hay algunas circunstancias en las que es útil para declarar el constructor de una clase abstract ser public, en lugar de protected o paquete-privada?

Esto no es del todo un duplicado de la pregunta "Abstract class constructor access modifier": claramente se puede declara un constructor para ser public; Quiero saber si alguna vez hay buena razón para hacerlo. Me parece que no hay. Veo que C# has a similar peculiarity.

+0

El constructor no tiene nada que ver con la "Creación" del objeto. Es solo un método que se llama al "crear" un objeto. Por lo tanto, la clase abstracta puede tener constructores públicos a los que se llamaría al crear una instancia de la clase abstracta (a través de la subclase) y en ese método de constructor, se escribiría el código para inicializar las variables miembro. http://stackoverflow.com/questions/260666/can-a-abstract-class-have-a-constructor?lq=1 –

+1

Los constructores también pueden ser 'privados', que se pueden usar en el encadenamiento de constructores. –

Respuesta

16

La respuesta es la misma para Java:

no hay razón para un constructor público para una clase abstracta. Asumo que la razón por la que el compilador no se queja es tan simple que simplemente no se tomó el tiempo para cubrir eso, ya que realmente no importa si es público o está protegido. (source)

No se puede llamar a un constructor de una clase abstracta desde otra cosa que no sea una subclase directa.

Así que agregar una regla especial para los modificadores de acceso de los constructores de clases abstractas no agregaría algo útil al lenguaje.


Una cosa que se ve como una excepción a esta regla - si la clase abstracta sólo define un constructor por defecto, entonces la subclase no tiene que implementar un constructor: esto es legal:

public abstract class A { 
    public A() {} 
} 

public class B extends A {} 

Así que podemos crear un B llamando al new B() - pero tenga en cuenta que aún crear un B y no un A. Y, de nuevo, no importa si el constructor en A es público o está protegido. Simplemente no debe ser privada, pero el compilador dará cuenta y se quejan ...

realidad que invocar un "invisible" constructor público predeterminado en B la que hace un simple super() llamada ...

-8

Usted puede tener un constructor público si no define en un constructor en la subclase. ejemplo

abstract class Animal { 
    String name; 
    public void Animal(String name) { 
     this.name = name; 
    } 
} 


class Cat extends Animal{ 
    public String sayMayName() { 
     return this.name; 
    } 
} 

myCat = new Cat("tester"); 

name = myCat.sayMyName(); 

si ningún constructor se define el constructor de la clase padre será llamado, si no es pública, no funcionará. Esto creo que se hace de forma más elegante con un patrón de fábrica, pero lo usé en la práctica en PHP y funciona bien.

+3

Esto no funciona en Java. Además, no está definiendo un constructor en la clase 'Animal', porque especifica un tipo de retorno (' void'). –

+2

Esto no compilaría: un constructor es * obligatorio * en 'Cat' porque' Animal' tiene un constructor (no predeterminado) ('public void Animal (String name)' no es un constructor de todos modos) –

+0

Esto solo funcionaría con un constructor sin argumentos. Pruébalo, tu código no se compilará. Pero el constructor predeterminado implícito siempre tendrá la visibilidad de la clase en sí, independientemente de cuál sea el constructor de la superclase. – biziclop

-7

Llámame hereje, pero ... Veo al menos un uso para un constructor en una clase abstracta.

Esto es: para especificar cómo son los parámetros del constructor.

Especifique un constructor abstracto (lo que hace que la clase sea abstracta). Las clases derivadas deben implementar este constructor con su firma específica para perder el estado abstracto.

No veo otra manera de especificar firmas de constructor obligatorias (ayúdenme si lo hace).

+3

Hacer que el constructor 'protected' aún le permita" especificar cómo son los parámetros del constructor ". – Raedwald

+0

cierto, pero hacerlo requiere que la clase derivada llame a super() o arriesgue que falten pasos de inicio que puedan ocurrir. El resumen aclara que esta es solo la firma, no hay implementación. - Sería mejor si las interfaces permitieran especificar la firma del constructor. Pero como no lo hacen, considero que las clases abstractas son la mejor alternativa. – foo

+3

No puede evitar llamar 'super'. Se llama implícitamente si no lo llamas explícitamente. – Raedwald

0

La visibilidad también influye en lo que se muestra en el javadoc (si se selecciona para excluir ciertos niveles de visibilidad). Como no importa lo contrario, podría ser un uso para un constructor público de una clase abstracta.

Si no proporciona ningún constructor, el constructor predeterminado es público si la clase es pública. La opción más fácil sería permitir eso, en lugar de forzar constructores protegidos.

En ese sentido, la pregunta inversa puede aclarar: ¿por qué no fuerzan a los constructores protegidos en clases abstractas? Porque los constructores públicos no cambiarán nada, por lo que tomaría tiempo y agregaría complejidad.

Cuestiones relacionadas