Ai mở rộng giao diện? Và tại sao?


20

AFAIK, extendscác lớp và implementsgiao diện cha mẹ lớp của tôi . Nhưng tôi chạy qua một tình huống, nơi tôi không thể sử dụng implements SomeInterface. Đây là tuyên bố của một loại chung chung. Ví dụ:

public interface CallsForGrow {...}

public class GrowingArrayList <T implements CallsForGrow>  // BAD, won't work!
                              extends ArrayList<T> 

Ở đây sử dụng implementsbị cấm về mặt cú pháp. Tôi nghĩ đầu tiên, việc sử dụng giao diện bên trong <> hoàn toàn bị cấm, nhưng không. Có thể, tôi chỉ phải sử dụng extendsthay vì implements. Kết quả là, tôi đang "mở rộng" một giao diện. Một ví dụ khác hoạt động:

public interface CallsForGrow {...}

public class GrowingArrayList <T extends CallsForGrow>  // this works!
                              extends ArrayList<T> 

Đối với tôi nó có vẻ như là một sự không nhất quán cú pháp. Nhưng có lẽ tôi không hiểu một số tính năng của Java 6? Có những nơi khác mà tôi nên mở rộng giao diện? Giao diện, mà tôi muốn mở rộng, có một số tính năng đặc biệt?

Câu trả lời:


25

Trong trường hợp các biến kiểu chung, trình biên dịch không thực sự quan tâm nếu Tlà một lớp, một giao diện, một enum hoặc một chú thích. Tất cả những gì nó quan tâm là nó là một loại với một tập hợp các loại phụ và siêu loại nhất định.

Và không có lý do gì để làm phức tạp cú pháp chỉ vì ở một nơi khác (nơi bạn thực sự thực hiện một giao diện), sự khác biệt giữa các lớp và giao diện có liên quan (ví dụ: nếu bạn implementlà một giao diện, bạn cần thực hiện tất cả các phương thức mà nó định nghĩa, nhưng bạn không cần, nếu bạn extendlà một lớp (không trừu tượng).

Giả sử trong một khoảnh khắc bạn phải viết implementsở đây, thì bạn cũng cần một cú pháp riêng cho enumcác giá trị (thay vì chỉ đơn giản là viết<E extends Enum<E>> ) và chú thích (mà bạn có thể dễ dàng khai báo bằng cách sử dụng <A extends Annotation>).

Nơi duy nhất mà bạn cần viết implementslà tại điểm mà bạn thực sự thực hiện giao diện. Tại đó điểm (và điểm chỉ) Sự khác biệt là rất quan trọng, bởi vì bạn phải thực hiện các biện pháp quy định tại giao diện. Đối với những người khác, không có vấn đề gì nếu bất kỳ được đưa ra Alà một lớp cơ sở hoặc một giao diện được triển khai củaB : đó là một loại siêu và đó là tất cả những gì quan trọng.

Cũng lưu ý rằng có một nơi khác mà bạn sử dụng extendsvới giao diện:

interface A {
}

interface B extends A {
}

Lúc này implementssẽ sai, vì B không thực hiện A .


Nếu chúng tôi sẽ sử dụng logic của bạn, chúng tôi nên sử dụng ' luôn mở rộng một số khuôn mặt' , không chỉ trong tổng quát.
Gangnus

2
@Gangnus: không, bởi vì đối với người triển khai có một sự khác biệt cụ thể giữa extendsimplements, chỉ khi nhìn vấn đề từ góc độ hệ thống thuần túy, không có sự khác biệt.
Joachim Sauer

1
Xin lỗi, tôi không hiểu suy nghĩ của bạn. --1. Tại sao chúng ta nên sử dụng "phối cảnh hệ thống kiểu thuần túy" trong một trường hợp chứ không phải trong trường hợp khác? --2. Tại sao nhu cầu cú pháp thay đổi ở những nơi khác nhau? Bạn có thể giải thích nó, xin vui lòng. Trong câu trả lời, nếu có thể.
Gangnus

1
@Gangnus: ai nói đó Tlà một lớp? Tcó thể tham chiếu một loại giao diện hoặc một enumloại.
Joachim Sauer

1
đến từ C #, toàn bộ cuộc thảo luận này là vô lý. chúng tôi biểu thị siêu kiểu của một loại với :. và dưới vỏ bọc, một giao diện luôn luôn là một lớp trừu tượng với ràng buộc chỉ chứa các abstractthành viên ảo ( ) chưa được thực hiện , để cho phép nhiều kế thừa. có nghĩa là không có sự khác biệt giữa implementsextends. cả hai có thể được thay thế bằng cùng một từ ( extends) hoặc bởi một số ký hiệu tùy ý ( :) và không có gì sẽ bị mất.
sara

5

Khi Java 5 và đặc biệt là chung chung, ban đầu được cung cấp cho các nhà phát triển đã đăng ký sở thích, cú pháp khá khác nhau. Thay vì Set<? extends Foo>Set<? super Bar>nó đã có Set<+Foo>Set<-Foo>. Tuy nhiên, thông tin phản hồi là không rõ liệu +có nghĩa cụ thể hơn hay rộng hơn (nhiều lớp hơn) . Sun đã phản hồi lại phản hồi đó bằng cách thay đổi cú pháp, nhưng trong giới hạn không giới thiệu từ khóa mới, đây sẽ là một vấn đề cho khả năng tương thích ngược.

Kết quả là không phải là khá tự nhiên. Khi bạn quan sát,extends quá tải để nói về các lớp giao diện "mở rộng", không phải là ngôn ngữ được sử dụng trong các bối cảnh khác; và superbị quá tải có nghĩa là "là một siêu lớp của", đó là hướng ngược lại của mối quan hệ được thể hiện trước đây bởi từ khóa, tức là đề cập đến một siêu lớp.

Tuy nhiên, các nguyên tắc cơ bản của giao diện không bị ảnh hưởng bởi thay đổi này và nó không giới thiệu các giao diện đặc biệt được mở rộng theo cách mới.


+1. Tôi thấy và đồng ý. Nhưng Joachim Sauer đã tìm thấy suy nghĩ sai lầm của tôi rằng T nhất thiết phải là một lớp học. Vì vậy, câu trả lời là của mình. Sự hiểu biết của bạn là một (hoặc 2) tầng cao hơn :-). Vấn đề của tôi là nguyên thủy hơn. Dù sao cũng cảm ơn bạn vì sự phát triển của tôi
Gangnus

2

Có những bất lợi trong cả việc cho phép và cấm cú pháp như vậy, và những điều cho phép là lớn hơn nhiều.

Chỉ cần nghĩ về nó.

Tách giao diện và thực hiện là một trong những thành ngữ lập trình cơ bản. Do đó, cú pháp cho phép đánh vần "giao diện thực hiện một cái gì đó" sẽ tệ như một sử dụng dấu cộng để biểu thị phép nhân của toán hạng.


Được. Vì vậy, tôi thực sự không hiểu điều gì đó. Tôi coi đó là rất có thể. Nhưng bạn đã giải thích vấn đề này, xin lỗi. T là một đại diện của một lớp. Tại sao ở một nơi tôi sử dụng T kéo dài và ở một T khác thực hiện?
Gangnus

@Gangnus trong ví dụ bạn cung cấp T đề cập đến tham số loại không nhất thiết phải là một lớp - hãy xem những gì Joachim đã nói với bạn . Cho phép thực hiện cho nó sẽ dẫn đến cùng một mớ hỗn độn mà tôi đã đề cập
gnat

Vâng, tôi đã thấy bình luận của anh ấy. Nó sẽ được đánh dấu là câu trả lời khi đưa vào câu trả lời. Cho đến khi cả hai bạn đều có lời cảm ơn và +1.
Gangnus

-1

Người ta cần hiểu lập trình hướng giao diện là bước tiếp theo trong khi hiểu giao diện. Nó cho biết thực tế sử dụng giao diện là gì. Vai trò của nó trong chương trình Java (hoặc bất kỳ ngôn ngữ nào khác).


2
Làm thế nào để câu trả lời của bạn giải quyết mối quan tâm của OP? Vui lòng chỉnh sửa câu trả lời của bạn để rõ ràng hơn.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.