2009-04-08 16 views
5

Tengo una clase base que tiene un método abstracto getType(). Quiero que las subclases puedan implementar este método y proporcionar la clase real para usar.Devuelve un tipo de clase anidada en Java

En el código, algo así como lo siguiente:

public abstract class A { 
    public static interface Tile; 

    protected abstract Class<Tile> getTileClass(); 
} 

public class B extends A { 
    public static class MyTile implements A.Tile { } 

    @Override 
    protected abstract Class<A.Tile> getTileClass() { 
     MyTile t = new MyTile(); // WORKS 
     return MyTile;   // ERROR HERE 
    } 
} 

El problema aquí es que me sale "MyTile no se puede resolver" en la línea marcada. Así que estoy tratando de devolver este lugar:.

retorno nueva MyTile() getClass()

pero ahora Eclipse me dice:

coinciden los tipos: no se puede convertir de Clase < capture # 1-of? se extiende B.MyTile > a la Clase < A.Tile >

la que ni siquiera estoy seguro si hay tal vez un error en Eclipse aquí arriba (captura # 1?).

A continuación, renuncio a las interfaces y trato de utilizar una clase de mosaico base abstracta. Con la ayuda de Eclipse, termino con el siguiente código que parece compilar:

public abstract class A { 
    public static abstract class Tile; 

    protected abstract Class<? extends Tile> getTileClass(); 
} 

public class B extends A { 
    public static class MyTile exends A.Tile { } 

    @Override 
    protected abstract Class<? extends A.Tile> getTileClass() { 
     return new MyTile().getClass(); // WORKS 
     return MyTile;     // "Cannot be resolved" 
    } 
} 

Así que, básicamente, parecen tener tres preguntas:

1) ¿Es posible conseguir que esto funcione con A . ¿El azulejo es una interfaz?

2) Cuando se utiliza una clase base, ¿es realmente correcto el Class<? extends X>?

3) ¿Y cómo puedo devolver mi referencia de clase B.MyTile anidada desde dentro del método? Tener que hacer new MyTile().getClass() no puede ser correcto, ¿verdad?

+0

Probablemente devolver una 'Clase' en lugar de un objeto no reflectivo es una mala idea. –

+0

@Tom Devolver una clase en el contexto de tipos verificados es un patrón muy común, que le permite comprobar el tipo * checked * de, por ejemplo, una colección, en tiempo de ejecución. No sé de otra manera, de hecho ... – Varkhan

Respuesta

6

Los genéricos y la anulación de tipo covariante no funcionan muy bien juntos. Debe declarar explícitamente que getTileClass() devuelve una clase que puede ser una subclase de A.Tile.

También puede acceder al objeto de clase de MyTile sin instanciarlo, con MyTile.class.

Tal vez puedas probar:

public abstract class A { 
    public static interface Tile; 

    protected abstract Class<? extends Tile> getTileClass(); 
} 

public class B extends A { 
    public static class MyTile implements A.Tile { } 

    @Override 
    protected Class<MyTile> getTileClass() { 
     return MyTile.class; 
    } 
} 

Aún mejor sería hacer un genérico. Usted todavía tiene que utilizar extiende en la definición de tipo de clase, pero puede ser un poco más específico:

public abstract class A<T extends A.Tile> { 
    public static interface Tile; 

    protected abstract Class<? extends T> getTileClass(); 
} 

public class B extends A { 
    public static class MyTile implements A.Tile { } 

    @Override 
    protected Class<MyTile> getTileClass() { 
     return MyTile.class; 
    } 
} 
+0

probablemente copie y pegue el error, pero ¿puede un método abstracto tener un cuerpo? correcto debe ser "protegido Clase getTileClass {..." –

+0

@Carlos sí, eso fue un exceso de entusiasmo c/p – Varkhan

+0

Buena respuesta. ¿ES este un problema solo por la covarianza o en general? – Uri

-1
public abstract class A { 
    public static interface Tile {}; 

    // I return something that is-a Tile 
    protected abstract Tile getTileClass(); 
} 

public class B extends A { 
    public static class MyTile implements A.Tile { } 

    @Override 
    protected abstract Tile getTileClass() { 
     return new MyTile(); 
    } 
} 

No hay necesidad de medicamentos genéricos, lo que desea decir que devuelva una baldosa o azulejo subclase.

Dicho sea de paso, una interfaz pública estática en una clase es un "olor a código"; o bien protegerlo, de modo que solo las subclases de A puedan implementar Tile o ponerlo en su propia interfaz de nivel superior. Poner en un pero permitir que cualquiera lo implemente envía un mensaje mixto.

Cuestiones relacionadas