Có sự khác biệt nào giữa các giao diện và các lớp trừu tượng chỉ có các phương thức trừu tượng không?


9

Giả sử chúng ta có một lớp trừu tượng và để cho lớp này chỉ có các phương thức trừu tượng. Là lớp trừu tượng này khác với một giao diện chỉ có cùng phương thức?

Điều tôi đang muốn biết là liệu có sự khác biệt nào cả về mặt triết học, khách quan và trong việc triển khai ngôn ngữ lập trình cơ bản giữa một Lớp Trừu tượng chỉ có các thành viên trừu tượng và Giao diện tương đương không?


ngôn ngữ nào?
kevin cline

theo như tôi có thể nói, câu hỏi của bạn được trả lời hai lần : ở đâyở đây . Và hai câu trả lời này là bất khả tri về ngôn ngữ, không có gì cụ thể cho C # ở đó
gnat

3
@blank Tôi không đồng ý với trạng thái trùng lặp được áp dụng cho câu hỏi của bạn để tôi mở lại. Hơn nữa tôi đã chỉnh sửa câu hỏi của bạn để làm rõ hơn những gì tôi tin rằng bạn đang hỏi.
maple_shaft

Câu trả lời:


22

Về mặt kỹ thuật, sự khác biệt không thực sự đáng kể nhưng về mặt khái niệm, chúng là những thứ hoàn toàn khác nhau và điều đó dẫn đến sự khác biệt về kỹ thuật mà những người khác đã đề cập.

Một siêu lớp trừu tượng chính xác là những gì nó nghe, nó là một loại phổ biến được chia sẻ bởi nhiều loại khác, như Mèo và Chó là Động vật.

Một giao diện cũng chính xác như những gì nó nghe, đó là một giao diện mà qua đó các lớp khác có thể giao tiếp với đối tượng. Nếu bạn muốn thực hiện Cat Walk, bạn vẫn ổn, vì Cat thực hiện giao diện CanWalk. Tương tự đối với một con Thằn lằn, mặc dù chúng đi rất khác nhau. Mặt khác, một con Rắn không thực hiện CanWalk, vì vậy bạn không thể bảo nó đi bộ. Trong khi đó, Lizard và Snake (hoặc có thể là các lớp con rõ ràng hơn - tôi không phải là chuyên gia) có thể vừa lột da, và do đó thực hiện CanShed, trong khi một con mèo không thể làm điều đó.

Nhưng tất cả chúng vẫn là Động vật và có một số thuộc tính chung, như chúng còn sống hay đã chết.

Đây là lý do tại sao tất cả các phương thức trên một giao diện phải được triển khai ở chế độ công khai (hoặc rõ ràng, trong C #). Nguyên nhân điểm trong giao diện bị ẩn khỏi lớp giao tiếp với đối tượng là gì? Đó cũng là lý do tại sao bạn có thể có nhiều giao diện cho một đối tượng, ngay cả khi một ngôn ngữ không hỗ trợ nhiều kế thừa.

Để trở lại câu hỏi của bạn, khi bạn nhìn nó theo cách này, rất hiếm khi có một lý do để có một siêu lớp hoàn toàn trừu tượng.


4
+1, mặc dù mèo rơi ra theo cách khó chịu hơn nhiều so với rắn hoặc thằn lằn.
Matthew Flynn

Về mặt kỹ thuật: Các phương pháp trừu tượng có thể được thực hiện bảo vệ. Phương pháp giao diện không thể.
Jacques Koorts

19

Trong hầu hết các ngôn ngữ OOP, một lớp triển khai chỉ có thể xuất phát từ một lớp trừu tượng, nhưng thực hiện nhiều giao diện.


3
phần lớn? bạn đang đếm cái nào Hầu hết các ngôn ngữ OOP tôi biết không có giao diện hoặc các lớp trừu tượng. C ++ chỉ có các lớp trừu tượng.
kevin cline

10
@kevincline: có thể là C #, Java và VB.NET.
tdammers

1
@kevincline, tôi nghĩ chỉ thiếu "có cả hai". IIRC, trong Ada, động lực cho giao diện là một, các nhà thiết kế không muốn có một tính năng thừa kế chung nhưng trường hợp đặc biệt của giao diện được coi là quá quan trọng không được cung cấp.
AProgrammer

@tdammers: LOL. Đó một trò đùa, phải không?
kevin cline

3

Trong một ngôn ngữ như C ++ cho phép nhiều kế thừa và không có giao diện, các lớp trừu tượng trong đó tất cả các phương thức là trừu tượng có thể đóng vai trò là giao diện. Tôi đã không làm việc với C ++ nhiều như vậy, nhưng tôi đoán nhiều kế thừa có thể gây ra vấn đề khi có các phương thức có cùng tên trong các lớp cơ sở.

Trong các ngôn ngữ như PHP và C #, các giao diện cung cấp một phương tiện để đạt được tính đa hình tương tự, mặc dù tôi không thích gọi nó là "thừa kế" vì có sự khác biệt về khái niệm giữa việc kế thừa một lớp trừu tượng và thực hiện giao diện. Các giao diện loại bỏ vấn đề xung đột, vì bản thân chúng không cung cấp thực hiện.

Một giao diện đóng vai trò như một hợp đồng với thế giới bên ngoài, trong khi một lớp trừu tượng có thể cung cấp một triển khai, mặc dù nếu được sử dụng để "giả" một giao diện, rất có thể nó sẽ không.

Sự khác biệt về khái niệm chính là khi một lớp kế thừa một lớp khác (trừu tượng hay không), có một mối quan hệ "là", vì vậy a Carlà một VehicleDoglà một Animal. Với một giao diện, đó là những gì đối tượng làm điều đó quan trọng. Vì vậy, cả CarDogcó thể Move()và người tiêu dùng biết điều đó bởi vì họ thực hiện Movable, nhưng một chiếc Xe chắc chắn không phải là một Dog, hoặc một Animal. Và việc thực hiện di chuyển sẽ khác nhau (bánh xe so với chân) nhưng mã tiêu thụ không và không nên quan tâm. Các giao diện là tất cả về mã tiêu thụ, chứ không phải là việc thực hiện.

Điểm chính là nếu bạn có giao diện bằng ngôn ngữ bạn chọn, hãy sử dụng chúng cho những thứ mà chúng ở đó. Nếu không (như trong C ++), bạn có thể giả mạo chúng bằng cách sử dụng các lớp trừu tượng thuần túy.


Giao diện cũng là một loại, vì vậy bạn có thể có một IAnimal cả hai DogCat .
Amy Blankenship

Bạn có thể, nhưng theo tôi, các giao diện là về hành vi tiếp xúc với thế giới bên ngoài, và không quá nhiều về những gì các đối tượng. Kế thừa ngụ ý rằng một cái gì đó là một loại của một cái gì đó khác (Cat là một động vật). Một giao diện chỉ nói những gì đối tượng có thể làm. Đó là lý do tại sao tôi muốn nói rằng một cái gì đó "thực hiện" thay vì "kế thừa từ" một giao diện, đó là điều mà hầu hết những người .Net mà tôi đã làm việc sẽ nói (tôi đoán vì cú pháp giống nhau đối với kế thừa và thực hiện).
Ivan Pintar

2

Các lớp trừu tượng có thể có các phương thức được bảo vệ trừu tượng (bằng ngôn ngữ tôi đang làm việc), trong các phương thức giao diện thường luôn công khai. Cho dù sự khác biệt này cho phép khai thác hữu ích tôi không biết.

Chỉnh sửa Đầu tiên tôi nghĩ rằng một phương thức trừu tượng riêng tư không có tác dụng, nhưng bây giờ tôi nhớ lại rằng nó có thể được sử dụng để đảm bảo rằng phương thức đó không bao giờ được gọi. Bằng cách này bạn có thể ngăn chặn rằng một hàm tạo sao chép của một đối tượng được gọi.


1
Các phương thức ảo được bảo vệ (có thể ghi đè) có thể hữu ích cho các lớp là một phần của khung hoặc một cái gì đó tương tự. Bằng cách đó, họ đảm bảo rằng mã tùy chỉnh trong một lớp kế thừa bản tóm tắt cung cấp chức năng đó. Mặc dù điều này cũng có thể đạt được bằng cách kế thừa một giao diện trên lớp cơ sở nhưng không thực sự thực hiện các phương thức của nó
Ivan Pintar

Vâng, tôi đã suy nghĩ về một cái gì đó như thế, nhưng không có bất kỳ kinh nghiệm với nó, vì vậy không thể đánh giá. Cảm ơn các đầu vào.
Thomas

Chỉ cần một lưu ý. Trong một số ngôn ngữ, các phương thức ảo riêng có thể bị ghi đè trong các lớp dẫn xuất.
Johan Boulé

2

Vâng, họ khác nhau. Nếu không, các nhà thiết kế ngôn ngữ sẽ không cung cấp cả hai. Tôi biết hai ngôn ngữ phân tách các lớp và giao diện: Java và C #, bản sao đột biến của Java. Các nhà thiết kế đã tạo ra các giao diện để tránh hỗ trợ kế thừa nhiều lớp. Hầu hết các ngôn ngữ khác đều hỗ trợ kế thừa nhiều lớp và do đó không tách rời các lớp và giao diện.


2

Tôi nghĩ rằng sự khác biệt chính là: Trong một lớp trừu tượng - ngay cả khi tất cả các phương thức đều trừu tượng, chúng vẫn có thể cung cấp các thành viên dữ liệu (biến thể hiện) và một số mã cho các lớp thực hiện nó (dưới dạng phương thức riêng hoặc hàm tạo), khối tĩnh; làm một phần công việc cho các lớp phụ và giúp họ thực hiện.

Một tác dụng phụ tích cực: mã nằm ở một nơi nên một nơi để chỉnh sửa. các lớp con chỉ có thể gọi phương thức siêu lớp và sau đó làm một cái gì đó khác hoặc không có gì nếu các hành động siêu lớp là đủ cho trường hợp của chúng. Super class muốn mỗi lớp phụ đưa ra quyết định này vì vậy đã đánh dấu tất cả việc thực hiện của nó là trừu tượng (một số cũng có thể trống)

Không liên quan đến câu hỏi: nhưng có giao diện nghĩa là một lớp có thể thực hiện hai hợp đồng khác nhau. Vì vậy, đó là một lợi thế của giao diện so với siêu lớp trừu tượng


1
Không phải là các phương thức trừu tượng được định nghĩa mà không có bất kỳ triển khai nào và để lại việc thực hiện cho các lớp kế thừa?
Ivan Pintar

đúng rồi, tôi đoán đó chỉ là các biến, hàm tạo và phương thức tĩnh & riêng nếu bạn đếm chúng
tgkprog

@Pinetree, trong thực tế hầu hết thời gian bạn sẽ muốn ít nhất một chút mã "thực" trong Lớp trừu tượng của mình (ít nhất là trong ngôn ngữ tôi sử dụng, không có cấu trúc đặc biệt cho Lớp trừu tượng).
Amy Blankenship

@AmyBlankenship có, hầu hết các lớp trừu tượng đều có mã "thực" (đó là những gì họ đang ở đó). Nhưng tôi đã đề cập đến các phương thức trừu tượng, trong bối cảnh của một lớp trừu tượng thuần túy phục vụ như một giao diện trong một ngôn ngữ như C ++, không có giao diện.
Ivan Pintar
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.