2011-08-14 17 views
9

Tôi có cấu trúc sau:hiệp biến Return Gõ vào giao diện không biên dịch qua 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 không thành công với thông báo sau:

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 

Tuy nhiên, Eclipse có thể biên dịch nó tốt, và như xa như tôi có thể thấy nó nên biên dịch - FooBar của fooBar() phương pháp đáp ứng các hợp đồng của cả hai Foo và Bar của fooBar() phương pháp bằng cách sử dụng lợi nhuận covariant.

Đây có phải là lỗi trong bản dịch Eclipse hay trong javac không? Hoặc là có một cách để thuyết phục javac để biên dịch nó? Để tham khảo các tùy chọn javac của tôi trông giống như sau:

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

Cùng một vấn đề với phiên bản trình biên dịch mở jdk 1.6.0_22. nhưng nó hoạt động trong java7. –

+0

Chỉ cần thử nghiệm nó và có, do đó, nó không - tuyệt vời. –

+0

Có thể [trùng lặp] (http://stackoverflow.com/questions/11343238/java-implementing-multiple-interfaces-with-same-method-and-different-return-ty)? – amaidment

Trả lời

3

Bạn đang mở rộng cả Foo và Bar trong giao diện FooBar của mình. Như vậy bạn đang kế thừa hai phương thức với các kiểu trả về không tương thích. Java co-phương sai chỉ được phép khi nó sau Liskov thay thế. Aka, các loại ứng cử ghi đè phải là một lớp con của kiểu trả về bị ghi đè.

Trong ví dụ của bạn ở trên một cái gì đó giống như nên biên dịch này:

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

Trong mã OP, kiểu trả về của phương thức ghi đè * làm * subtype các kiểu trả về của cả hai phương thức ghi đè. Vì vậy, từ một quan điểm học tập, không có lý do tại sao mã OP không nên hợp lệ. –

1

The JLS (§9.4.1) nói:

Có thể cho một giao diện kế thừa một số phương pháp với chữ ký ghi đè tương đương (§ 8.4.2). Tình huống như vậy không phải trong chính bản thân số gây ra lỗi biên dịch. Giao diện được xem là kế thừa tất cả các phương thức. Tuy nhiên, một trong các phương thức kế thừa phải là phải là kiểu trả về có thể thay thế được cho bất kỳ phương pháp được kế thừa nào khác; cách khác, một lỗi thời gian biên dịch xảy ra (The ném khoản không nguyên nhân sai sót trong trường hợp này.)

Vì vậy, tôi sẽ nói javac đó là đúng. Nhưng điều này trông giống như thuật ngữ luật sư với tôi, vì vậy tôi có thể sai.

1

Câu trả lời trong số javaranch discussion dường như gợi ý rằng đó là lỗi javac. Tuy nhiên, tham chiếu bug url dường như không hoạt động.

+0

Có vẻ như [JDK-7u4] (http://www.oracle.com/technetwork/java/javase/downloads/jdk-7u4-downloads-1591156.html) sửa lỗi. – Georg

1

Là một khắc phục, bạn có thể làm

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

Không đẹp, nhưng nên làm các trick.

+1

Cảm ơn, đó là một ý tưởng tốt - tuy nhiên, khi nó biên dịch với javac OpenJDK 7 và với trình biên dịch eclipse tôi có thể làm việc xung quanh nó mà không cần giới thiệu thêm các loại. –

+1

Điều này có vẻ không hoạt động, javac của jdk6 vẫn nói 'các loại Bar1 và Foo1 không tương thích; cả hai đều định nghĩa fooBar(), nhưng với các kiểu trả về không liên quan'. –

1

Tôi đã gặp vấn đề tương tự và có vẻ như tốt bằng cách sử dụng JDK 7 từ Oracle.