2015-10-18 15 views
5

Trong ví dụ này trên hướng dẫn của trang web java page. Hai giao diện xác định cùng phương thức mặc định startEngine(). Lớp FlyingCar triển khai cả hai giao diện và phải ghi đè startEngine() do xung đột rõ ràng.Bối rối về từ khóa "siêu" trong ví dụ Java này

public interface OperateCar { 
    // ... 
    default public int startEngine(EncryptedKey key) { 
     // Implementation 
    } 
} 
public interface FlyCar { 
    // ... 
    default public int startEngine(EncryptedKey key) { 
     // Implementation 
    } 
} 

public class FlyingCar implements OperateCar, FlyCar { 
    // ... 
    public int startEngine(EncryptedKey key) { 
     FlyCar.super.startEngine(key); 
     OperateCar.super.startEngine(key); 
    } 
} 

Tôi không hiểu tại sao, từ FlyingCar, super được dùng để ám chỉ cả hai phiên bản startEngine() trong OperateCarFlyCar giao diện. Theo tôi hiểu nó, startEngine() không được định nghĩa trong bất kỳ lớp siêu nào, do đó không nên được gọi là cư dân trong một. Tôi cũng không thấy bất kỳ mối quan hệ giữa super và hai giao diện như thực hiện trong FlyingCar

+4

' super' của chính nó có nghĩa là siêu lớp. 'FlyCar.super' là mới trong Java 8, và có nghĩa là thực hiện trong giao diện' FlyCar'. – immibis

+1

Xem http://stackoverflow.com/questions/19976487/explicitly-calling-a-default-method-in-java – Eran

+1

Tại sao bạn không đọc hướng dẫn đó thay vì chỉ trích xuất mã ví dụ? – Holger

Trả lời

5

Theo tôi được biết, startEngine() không được định nghĩa trong bất kỳ lớp siêu, do đó không nên được gọi là cư dân trong một.

Có nó đã được xác định. Đó là việc thực hiện mặc định, ví dụ:

public interface OperateCar { 
    // ... 
    default public int startEngine(EncryptedKey key) { 
     // Implementation 
    } 
} 

OperateCar.super.startEngine(key) sẽ thực hiện việc thực hiện mặc định.

Nếu không có cài đặt mặc định, chỉ cần một phương pháp giao diện, sau đó tuyên bố sẽ không có ý nghĩa, như giao diện sẽ không chứa một thực hiện, như thế này:

public interface OperateCar { 
    // ... 
    int startEngine(EncryptedKey key); 
} 

Tôi cũng không thấy bất kỳ mối quan hệ nào giữa siêu và hai giao diện được triển khai trong FlyingCar

Không chắc tôi hiểu điều gì bạn đang hỏi. super là một cách để gọi triển khai trong giao diện chính. Nếu không có super, không có cách nào khác để diễn tả điều đó.

+0

Tôi biết có một triển khai mặc định, nhưng bạn có nghĩa là nó giả định một lớp mặc định (siêu) mà triển khai mặc định này đã được thực hiện? Nó có ý nghĩa logic theo cách đó. Và nếu có một lớp siêu mặc định, thì bây giờ tôi có thể thấy mối quan hệ giữa hai giao diện và 'super'. –

+2

@okeyxyz: không có thứ gì giống như “lớp siêu mặc định” và không rõ tại sao bạn nghĩ vậy. 'InterfaceName.super' là cú pháp để gọi một phương thức giao diện không trừu tượng từ một lớp thực hiện. Đó là nó. Có vẻ như thế này * bởi vì các nhà thiết kế Java Language đã nói như vậy *. Các phương thức giao diện không trừu tượng này được gọi là các phương thức 'default', vì chúng cần từ khóa đó để đánh dấu là không trừu tượng. Đó là để tương thích với các phiên bản ngôn ngữ trước đó, trong đó 'abstract' được ngụ ý, ngay cả khi không được chỉ định * và * vì các nhà thiết kế Java Language đã nói như vậy. – Holger

5

Khi bạn có một lớp triển khai nhiều giao diện và các giao diện đó chứa các phương thức có chữ ký phương thức tương tự (ví dụ: phương thức startEngine của bạn).

Để biết được phương pháp mà bạn đang đề cập đến, bạn làm:

yourInterface.super.method(); 

Bạn có thể có một cái nhìn tại link này cũng đề cập đến câu hỏi của bạn.

Vì vậy, bạn cũng có thể làm điều này:

public class FlyingCar implements FlyCar, OperateCar{ 
    public int startEngine(EncryptedKey key) { 
     return FlyCar.super.startEngine(key); 
    } 
} 

Hoặc này:

public class FlyingCar implements FlyCar, OperateCar{ 
    public int startEngine(EncryptedKey key) { 
     return Operate.super.startEngine(key); 
    } 
} 

Dù bằng cách nào, bạn phải xác định giao diện bạn đang gọi phương pháp này từ, nếu bạn chỉ đơn giản là gọi phương thức từ giao diện.

Tuy nhiên, tình huống cụ thể này là một ví dụ cho một lý do. Điều sẽ có nhiều khả năng xảy ra hơn là bạn sẽ làm một việc như sau:

public int startEngine(EncryptedKey key) { 
    // Custom implemenation... 
} 

Điều gì cũng hợp lệ. Tuy nhiên, nếu bạn có hai giao diện với một phương thức có chữ ký giống nhau, đó cũng có thể là tình huống mà bạn nên có một giao diện cha đơn khai báo phương thức đó và hai giao diện con mở rộng nó:

public interface Car { 
    // ... 
    default public int startEngine(EncryptedKey key) { 
     // Default implementation 
}; 
} 

public interface FlyCar extends Car { 
    // Methods unique to FlyCar 
} 

public interface OperateCar extends Car { 
    // methods unique to OperateCar 
} 
+4

** Reamrks: ** Lưu ý rằng trình sửa đổi *** mặc định chỉ có sẵn trong Java 8 trở đi. – user3437460

Các vấn đề liên quan