2011-08-14 8 views
9

que tienen la siguiente estructura:covariante Tipo de retorno en la interfaz no compilar a través javac

public interface BarReturn {} 
public interface FooReturn {} 
public interface FooBarReturn extends FooReturn, BarReturn {} 

public interface Foo { 
    FooReturn fooBar(); 
} 

public interface Bar { 
    BarReturn fooBar(); 
} 

public interface FooBar extends Foo, Bar { 
    FooBarReturn fooBar(); 
} 

javac un error con el siguiente mensaje:

FooBar.java:2: types Bar and Foo are incompatible; both define fooBar(), but with unrelated return types 
public interface FooBar extends Foo, Bar { 
    ^
1 error 

Sin embargo, Eclipse puede compilar bien, y en la medida de como puedo ver, debería compilarse: el método fooBar() de FooBar satisface el contrato del método fooBar() de Foo y Bar mediante el uso de retornos covariantes.

¿Es esto un error en la compilación Eclipse o en javac? ¿O hay una forma de convencer a javac para compilarlo? Como referencia, mis opciones de javac son las siguientes:

javac -d /tmp/covariant/target/classes -sourcepath /tmp/covariant/src/main/java: /tmp/covariant/src/main/java/Foo.java /tmp/covariant/src/main/java/BarReturn.java /tmp/covariant/src/main/java/FooBarReturn.java /tmp/covariant/src/main/java/Bar.java /tmp/covariant/src/main/java/FooReturn.java /tmp/covariant/src/main/java/FooBar.java -g -nowarn -target 1.6 -source 1.6 
+0

Mismo problema con el compilador de jdk abierto versión 1.6.0_22. pero funciona en java7. –

+0

Acabo de probarlo y sí, así es, genial. –

+0

Posible [duplicado] (http://stackoverflow.com/questions/11343238/java-implementing-multiple-interfaces-with-same-method-and-different-return-ty)? – amaidment

Respuesta

3

Está ampliando tanto Foo como Bar en su interfaz FooBar. Como tal, estás heredando dos métodos con tipos de devolución incompatibles. La co-varianza de Java solo está permitida cuando sigue la sustitución de Liskov. Aka, los tipos de candidato principales deben ser una subclase del tipo de devolución anulada.

En el ejemplo anterior algo como esto debe de compilación:

public interface BarReturn {} 
public interface FooReturn {} 
public interface FooBarReturn extends FooReturn, BarReturn {} 

public interface Foo { 
    FooReturn fooBar(); 
} 

public interface FooBar extends Foo{ 
    FooBarReturn fooBar(); 
} 
+0

En el código de OP, el tipo de devolución del método de anulación * does * subtipo de los tipos de devolución de ambos métodos anulados. Entonces, desde un punto de vista académico, no hay ninguna razón por la cual el código del OP no sea válido. –

1

The JLS (§9.4.1) dice:

Es posible para una interfaz de heredar varios métodos con firmas de anulación equivalente (§ 8.4.2). Tal situación no en el propio causa un error en tiempo de compilación. La interfaz se considera heredar todos los métodos. Sin embargo, uno de los métodos heredados debe debe ser de tipo de retorno sustituible por cualquier otro método heredado; de lo contrario, se produce un error en tiempo de compilación (La lanza cláusulas no causan errores en este caso.)

, así que diría que es javac derecha. Pero esto parece una jerga de abogado para mí, así que podría estar equivocado.

1

Una respuesta en este javaranch discussion parece sugerir que es un error de javac. Sin embargo, el referido bug url no parece funcionar.

+0

Parece que [JDK-7u4] (http://www.oracle.com/technetwork/java/javase/downloads/jdk-7u4-downloads-1591156.html) corrige el error. – Georg

1

Como solución alternativa, se podría hacer

interface Foo1 extends Foo { 
    FooBarReturn fooBar(); 
} 
interface Bar1 extends Bar { 
    FooBarReturn fooBar(); 
} 
public interface FooBar extends Foo1, Bar1 { } 

No es bonita, pero debe hacer el truco.

+1

Gracias, es una buena idea, sin embargo, como compila con el javac de OpenJDK 7 y con el compilador de eclipse, puedo solucionarlo sin introducir tipos adicionales. –

+1

Esto no parece funcionar, javac de jdk6 todavía dice 'los tipos Bar1 y Foo1 son incompatibles; ambos definen fooBar(), pero con tipos de retorno no relacionados'. –

1

Tuve el mismo problema y parece estar bien al usar el JDK 7 de Oracle.

Cuestiones relacionadas