Tôi nên thực hiện một giao diện trực tiếp hoặc có siêu lớp làm điều đó?


14

Có sự khác biệt giữa

public class A extends AbstractB implements C
{...}

đấu với...

public class A extends AbstractB
{...}
abstract class AbstractB implements C
{...}

Tôi hiểu rằng trong cả hai trường hợp, lớp A sẽ kết thúc phù hợp với giao diện. Trong trường hợp thứ hai, AbstractBcó thể cung cấp triển khai cho các phương thức giao diện trong C. Đó có phải là sự khác biệt duy nhất?

Nếu tôi KHÔNG muốn cung cấp một triển khai cho bất kỳ phương thức giao diện nào AbstractB , tôi nên sử dụng kiểu nào? Việc sử dụng cái này hay cái kia có một số mục đích 'tài liệu' ẩn?


3
gợi ý về tiêu đề: tôi nên thực hiện giao diện trực tiếp hay để siêu lớp làm điều đó
Jeanne Boyarsky

Câu trả lời:


20

Tất cả phụ thuộc vào nếu về mặt AbstractB implements Cngữ nghĩa. Tức là nếu nó có ý nghĩa về mặt ngữ nghĩa AbstractBđể thực hiện C, thì hãy đi cho nó.

Nếu chúng ta lấy ví dụ cụ thể, sự khác biệt về ngữ nghĩa sẽ trở nên rõ ràng.

Nếu A = Dog, Tóm tắtB = Động vật, C = IBark

Chỉ có sự lựa chọn có ý nghĩa là

class Dog extends Animal implements IBark{

Điều này vô nghĩa, vì điều này sẽ ám chỉ rằng tất cả các loài động vật đều sủa.

class Animal implements IBark{

Sự khác biệt khác phát huy tác dụng nếu bạn có nhiều thứ hơn là chỉ class Athừa hưởng từ AbstractB. Ở # 1 họ không cần thực hiện C, ở # 2 họ buộc phải thực hiện C.


1
+1 rõ ràng hơn nhiều so với câu trả lời của tôi!
Thực phẩm điện tử cầm tay

Ngoài ra, nếu giao diện Heterotrophcó vẻ hợp lý để thực Animalhiện Heterotroph. Nếu bạn mong đợi rất nhiều động vật sủa khác và muốn đối xử với chúng theo cách tương tự, một lớp khác BarkingAnimal extends Animal implements IBarksẽ là con đường để đi.
Scarfridge

@scarfridge Thật ra tôi rất mong động vật sẽ gia hạn Heterotrophnhưng cảm ơn vì sự đóng góp của bạn
Karthik T

2

Cách dễ dàng để xác định mối quan hệ thừa kế phù hợp không phải là nhìn vào các lớp mà là mã gọi các phương thức trên các lớp đó. Ở đâu đó trong mã của bạn, bạn có một cái gì đó như AbstractB b = new A();hoặc otherObject.addAbstractB(this);. Dù bằng cách nào, sau này bạn sử dụng AbstractBtham chiếu đó để thực hiện các cuộc gọi phương thức khác nhau.

Trong tình huống đó, bạn sẽ muốn gọi phương thức của C? Nếu vậy thì AbstractBnên thực hiện C. Nếu không, nó không nên. Nếu bạn không có bất kỳ tình huống nào như vậy, thì bạn không cần thừa kế, và nên tái cấu trúc để sử dụng bố cục thay vì vì nó lỏng lẻo hơn nhiều.


2

Đây không phải là mục đích tài liệu "ẩn". Nó cho phép bạn truyền AbstractB và tất cả các lớp con của nó thành C. Thực tế có ba kiểu.

public class A extends AbstractB implements C
public class AbstractB

Tôi sẽ sử dụng cái này nếu AbstractB không triển khai logic C. Ngay cả khi nó không cung cấp các phương thức, nó có thể có ý nghĩa. Chẳng hạn như Dog mở rộng động vật thực hiện Wag. Nó không có ý nghĩa đối với tất cả các loài động vật đối với Wag. Lưu ý rằng phương pháp này không thực sự ngăn cản AbstractB cung cấp việc triển khai.

public class A extends AbstractB
public AbstractB implements C

Tôi sẽ sử dụng cái này nếu tôi muốn tất cả các lớp con thực hiện giao diện VÀ thật hợp lý khi tất cả chúng làm như vậy. Chẳng hạn như Beagle mở rộng AbstractDog thực hiện Wag.

public class A extends AbstractB implements C
public class AbstractB implements C

Điều này là dư thừa nhưng có thể thêm rõ ràng.


Tôi nghĩ "Tóm tắt" (không tồn tại trong câu hỏi) trong đoạn 2 nên được đổi thành "Tóm tắt". Tôi không thể chỉnh sửa để làm điều đó vì các biên tập viên phải có ít nhất 6 ký tự.
cellepo
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.