2009-01-20 13 views
5

A modo de ejemplo:En Java, ¿cómo hago una clase con un constructor privado cuya superclase también tiene un constructor privado?

public class Foo { 
    private Foo() {} 
} 

public class Bar extends Foo { 
    private Bar() {} 

    static public doSomething() { 
    } 
} 

Eso es un error de compilación allí mismo. Una clase necesita, al menos, invocar implícitamente el constructor predeterminado de su superclase, que en este caso no está visible en Foo.

¿Puedo llamar objeto 's constructor de barra en su lugar?

+0

¿Hay alguna razón para que Foo() {} sea privado en lugar de estar protegido? –

+1

@svelil: Digamos que está en una biblioteca de terceros, o que está fuera de mi control, y quiero crear una subclase. –

Respuesta

10

No puede. Es necesario que sea confidencial paquete constructor de Foo por lo menos (Aunque yo probablemente sólo lo hacen protegido

(Editar -. Los comentarios en este post un buen punto)

+0

Package-private es suficiente, si ambos se ponen en el mismo paquete. – starblue

+0

@starblue - Creo que es por eso que dijo 'al menos'. El paquete –

+0

es más restrictivo que el protegido, por lo que "al menos" es incorrecto. Si ambos estuvieran en la misma clase externa, creo que la construcción privada sería accesible. –

2

Usted no será capaz de crear una instancia de barra durante el tiempo que Foo tiene un constructor privado. La única manera de que sería capaz de hacerlo es si Foo tenía un constructor protegido.

+2

Si una superclase tiene un constructor privado, entonces la subclase ni siquiera se compilará. –

1

no se puede llamar al constructor del objeto directamente de bar, mientras que se trata de una subclase de Foo, tendría que hacerlo a través del constructor de Foo, que es privado en este caso.

Cuando declara Foo's c onstructor private, no crea un constructor público predeterminado. Como la barra tiene para invocar al constructor de Foo, no es posible dejarla en privado. Sugeriría, como otros lo han hecho, usar protegidos en lugar de privados.

7

Esto es realmente un síntoma de una mala forma de herencia, llamada herencia de implementación. O bien la clase original no fue diseñada para ser heredada, y por lo tanto eligió usar un constructor privado, o que toda la API está mal diseñada.

La solución para esto no es encontrar una manera de heredar, sino ver si puede componer el objeto en lugar de heredar, y hacerlo a través de interfaces. Es decir, la clase Foo ahora es la interfaz Foo, con un FooImpl. Entonces la barra de interfaz puede extender Foo, con un BarImpl, que no tiene relación con FooImpl.

Dentro de BarImpl, podrías si deseas reutilizar algunos códigos, tener un FooImpl dentro como miembro, pero eso depende completamente de la implementación y no estará expuesto.

Cuestiones relacionadas