- ¿Cómo podría simular herencia múltiple en Java? Sé que se puede conseguir
implementando Interfaces en una clase, pero le he dado vueltas al asunto y
aún no lo tengo muy claro.
Un cordial saludo, ;-)
Crea una clase que implemente varias interfaces y dentro desarrolla los
métodos de las interfaces.
Ej.
class MiClase implements Interface1, Interface2, ...
{
void Metodo1Interface1
{
Tu código
}
void Metodo2Interface1
{
Tu código
}
.
.
.
void Metodo1Interface2
{
Tu código
}
.
.
.
}
Fco Javier Pulido Vaquero wrote:
>
> ¿Puedes aclararme un poco?
>
> - ¿Cómo podría simular herencia múltiple en Java? Sé que se puede conseguir
> implementando Interfaces en una clase, pero le he dado vueltas al asunto y
> aún no lo tengo muy claro.
>
Un modo de simularlo es con las inner classes.
Digamos que tienes clases A y B y quieres que C tenga acceso a la
implementación protegida de A y B. Una cosa que se puede hacer es hacer
que C sea una subclase de A pero una inner class de B (o vice versa).
class A {
}
class B {
class C extends A {
// El código dentro de C puede invocar todos los métodos de A
// y de B, ya que está asociado con una instancia de clase B.
}
}
Espero que esto ayude.
Jonathan Revusky
--
Available for Java and Delphi Consulting
Make your .class files double-clickable
with SmartJ
http://www.bigfoot.com/~crystalline.solutions
Jonathan, no lo entiendo. Espero que no sean especificaciones de la 1.2
Yo he hecho:
----------------8<-----------------
class A{
private void mensajeA(){ System.out.println("Soy a"); }
}
class B{
private void mensajeB(){ System.out.println("Soy b"); }
class C extends A{
public void mensajes(){
mensajeA();
mensajeB();
}
}
}
class D{
public static void main(String s[]){
C c = new C();
c.mensajes();
}
}
----------------8<-----------------
Con lo que C extenderia A y B a la vez.
Como respuesta, al compilar obtengo:
prb.java:10: No method matching mensajeA() found in inner class B. C.
mensajeA();
^
prb.java:18: Class C not found in type declaration.
C c = new C();
^
prb.java:18: Class C not found in type declaration.
C c = new C();
^
Tengo claro que los dos ultimos errores son ciertos, ya que C no puede
ser instanciada ya que su ambito se restringe a la clase B.
Pero el primero de ellos parece que dice que C no "extiende" A.
Un poco raro ¿no?
--
Juan Gonzalo de Silva Medina
http://www.caymasa.es/usr/gonzalo
mail:gon...@caymasa.es
Powered by Red Hat 5.1 2.0.35 and Java
No, esto tiene que ver con el lenguaje y el lenguaje en sí no ha
cambiado entre 1.1 y 1.2. Muchos nuevos API's, pero el lenguaje es el
mismo.
> Yo he hecho:
>
> ----------------8<-----------------
> class A{
> private void mensajeA(){ System.out.println("Soy a"); }
> }
Tendría que ser algo como:
protected void mensajeA()
ya que incluso las subclases de A no pueden acceder a la implementación
"private". Tiene que ser "protected".
> class B{
> private void mensajeB(){ System.out.println("Soy b"); }
> class C extends A{
> public void mensajes(){
> mensajeA();
> mensajeB();
> }
> }
> }
> class D{
> public static void main(String s[]){
> C c = new C();
> c.mensajes();
> }
> }
La clase D no puede ser compilada porque no hay ninguna instancia de B a
la que la instancia de clase C puede ser asociada. (¿Eso es claro
acaso?)
De hecho, necesitarías algo como:
class B {
private void mensajeB() {...}
class C extends A {
....
}
C createC() {
return new C();
}
}
class D {
public static void main(String s[]){
B b = new B();
C c = b.createC();
c.mensajes();
}
}
> ----------------8<-----------------
>
> Con lo que C extenderia A y B a la vez.
No extiende A y B a la vez porque no hay herencia multiple en Java. Pero
es un modo de simularlo en cierto modo.
>
> Como respuesta, al compilar obtengo:
>
> prb.java:10: No method matching mensajeA() found in inner class B. C.
> mensajeA();
> ^
> prb.java:18: Class C not found in type declaration.
> C c = new C();
> ^
> prb.java:18: Class C not found in type declaration.
> C c = new C();
> ^
>
> Tengo claro que los dos ultimos errores son ciertos, ya que C no puede
> ser instanciada ya que su ambito se restringe a la clase B.
> Pero el primero de ellos parece que dice que C no "extiende" A.
El método tendría que ser "protected" por lo menos. "Private" es
realmente privado. No tiene acceso ni las subclases.
> Un poco raro ¿no?
Un poco rollo quizá... :-) Raro, no, porque, en realidad, todo está
funcionando como debe funcionar....
Un saludo,
>
> [...]
> Tendría que ser algo como:
>
> protected void mensajeA()
>
> ya que incluso las subclases de A no pueden acceder a la implementación
> "private". Tiene que ser "protected".
Vale, mala hora para probar...
>
> >[...]
> La clase D no puede ser compilada porque no hay ninguna instancia de B a
> la que la instancia de clase C puede ser asociada. (¿Eso es claro
> acaso?)
Ciertamente, no.
No entiendo lo que quieres decir por "asociada" ¿?.
>
> De hecho, necesitarías algo como:
>
> class B {
> private void mensajeB() {...}
> class C extends A {
> ....
> }
>
> C createC() {
> return new C();
> }
> }
>
> [...]
No me funciona, y sigo con lo mismo :-?, en la clase D no puede aparecer
ninguna referencia a la clase C ya que el compilador no puede encontrar
la definicion de la clase. Existe solamente dentro de la clase B.
> > Un poco raro ¿no?
>
> Un poco rollo quizá... :-) Raro, no, porque, en realidad, todo está
> funcionando como debe funcionar....
>
¿rollo? no creo, a mi me gusta urgar dentro, lo otro..., ya lo dice el
manual :-).
Saludos,
P.S.: Por la velocidad parece un chat ;-).
--
Juan Gonzalo de Silva Medina
Bien. Gracias, por decírmelo. A veces, tengo la incómoda sensación de
que he contestado algo de modo un tanto críptico quizá, pero que no me
piden que lo explicite más porque tienen miedo de parecer tontos o algo
así.
> No entiendo lo que quieres decir por "asociada" ¿?.
A ver. En el contexto de una clase, (por lo menos si no estamos en un
método estático) siempre hay una referencia implícita a una instancia de
la clase.
Se trata del "this".
En el caso de una clase interior, en realidad hay dos referencias tipo
"this". Hay una referencia a la clase en sí y la clase que la contiene.
La inner class y la outer class. En el código en cuestión:
class B {
private void mensajeB() {...}
class C extends A {
mensajeA(); // Es equivalente a this.mensajeA();
mensajeB(); // Esto es equivalente a B.this.mensajeB();
}
}
Es decir que hay dos referencias "this". Si hay que explicitar el "this"
de la clase exterior, se utiliza la sintaxis: OuterClass.this.methode();
Si entiendes todo esto, creo que se ve bastante fácilmente porque en la
clase D, no puedes instanciar la inner class C sin tener una instancia
de B. Cuando dije que no había ninguna instancia de B a la que la clase
C podía ser asociada, es lo que quería decir.
class B {
private void mensajeB() {...}
class C extends A {
....
}
C createC() {
// aquí, sí que hay una instancia implícita de la
// outer class B así que funciona.
return new C();
}
}
>
> No me funciona, y sigo con lo mismo :-?, en la clase D no puede aparecer
> ninguna referencia a la clase C ya que el compilador no puede encontrar
> la definicion de la clase. Existe solamente dentro de la clase B.
Me equivoqué en el ejemplo, de hecho. Eso suele ocurrirnos a los
mortales cuando entramos código directamente en Netscape sin verificar
que se compila. :-)
public class D {
public static void main(String s[]){
B b = new B();
B.C c = b.createC();
//Había que explicitar B.C,
//aunque se podría haber puesto: import B.*;
//todo arriba y entonces se podría haber escrito simplemente:
// C c = b.createC();
c.mensajes();
}
}
> ¿rollo? no creo, a mi me gusta urgar dentro, lo otro..., ya lo dice el
> manual :-).
>
> Saludos,
>
> P.S.: Por la velocidad parece un chat ;-).
Ya no. :-)
De todas formas, agrego abajo el código ilustrativo. He verificado que
sí que se compila y funciona. Como dije, es un modo de "simular" la
herencia múltiple ya que la clase B.C puede acceder transparentement a
la implementación protegida de las clases A y B.
De hecho, todo esto es mucho mejor que la herencia múltiple de C++ por
una variedad de motivos...
Jonathan Revusky
--
Available for Java and Delphi Consulting
Make your .class files double-clickable
with SmartJ
http://www.bigfoot.com/~crystalline.solutions
-------------------------------------------------------------
// El fichero D.java que ilustra
// algunos puntos finos sobre las inner clases.
class A {
protected void mensajeA(){ System.out.println("Soy a"); }
}
class B {
private void mensajeB(){ System.out.println("Soy b"); }
class C extends A{
public void mensajes(){
mensajeA();
mensajeB();
}
}
C createC() {
return new C();
}
}
public class D {
public static void main(String s[]){
B b = new B();
B.C c = b.createC();
c.mensajes();
}
}
> [...]
Muchas gracias Jonathan ha sido de lo mas interesante.
Saludos,
--
Juan Gonzalo de Silva Medina
Ej.
class claseA implements InterfaceA
{ Implementar metodos de interfaceA, constructores, etc }
class claseB implements InterfaceB
{ Implementar metodos del interfaceB, constructores, etc }
class MiClase implements InterfaceA, InterfaceB
{
protected InterfaceA objA;
protected InterfaceB objB;
public MiClase
objA=(claseA) new InterfaceA;
objB=(claseB) new InterfaceB;
}
void Metodo1InterfaceA
// Tu código si quieres sobrecargar o
objA.Metodo1InterfaceA()
}
.
.
// Igual con el resto de métodos de InterfaceA
void Metodo1InterfaceB
// Tu código si quieres sobrecargar o
objB.Metodo1InterfaceB()
}
.
.
// Lo mismo con el resto de métodos del InterfaceB
}
Un cordial saludo ;-)