Tại sao sự kế thừa, đóng gói và đa hình không phải là trụ cột của OOP? [đóng cửa]


16

Một ngày nọ, tôi đến một cuộc trò chuyện Stack Overflow và thấy một cụm từ, nói rằng sự kế thừa, sự bao bọc và tính đa hình là những trụ cột của OOP (theo nghĩa là chúng là cơ bản, là đế xây dựng).

Ngoài ra, có một câu hỏi tương tự, tôi đã được hỏi rất thường xuyên trong các kỳ thi đại học và phỏng vấn xin việc, và câu trả lời đúng luôn là câu phát âm trong tiêu đề của câu hỏi ("Vâng, kế thừa, đóng gói và đa hình là những trụ cột của OOP ).

Nhưng trong cuộc trò chuyện Stack Overflow tôi đã bị chế giễu nghiêm trọng, những người tham gia không đồng ý với tuyên bố như vậy. Vì vậy, những gì sai với tuyên bố này?

Có phải các lập trình viên dường như được đào tạo về những điều khác nhau trong các trường đại học hậu Xô Viết và Hoa Kỳ?

Có phải sự kế thừa, đóng gói và đa hình không được coi là trụ cột của OOP bởi các lập trình viên Hoa Kỳ / Vương quốc Anh?


7
Câu hỏi của bạn không có ngữ cảnh; chúng tôi không biết những người trong cuộc trò chuyện SO đang nghĩ gì, hoặc họ đang phản ứng với điều gì. Có lẽ bạn có thể liên kết với cuộc trò chuyện trong phòng trò chuyện, vì vậy chúng ta có thể xem qua nó? Điều đó nói rằng, tôi nghĩ rằng điều này được giải quyết tốt nhất trong phòng trò chuyện, hơn là ở đây.
Robert Harvey

1
@Robert, quá nhiều thời gian đã qua. Tôi nghi ngờ nếu tôi thậm chí có thể tìm thấy liên kết đến cuộc trò chuyện. Nhưng tôi đồng ý rằng bối cảnh là quan trọng. Không phải để đổ lỗi cho ai đó, hoặc thể hiện mình là nạn nhân vô tội của một cuộc xâm lược trò chuyện, tôi chỉ muốn biết sự thật.
PaulD

5
Phòng chờ. Bạn đã mặc bộ đồ chống cháy của bạn đầu tiên?
Robert Harvey

1
Ý nghĩa duy nhất tôi có thể đưa ra cho câu là "bạn có thể có OOP mà không cần bất kỳ từ nào trong số chúng" (đúng, nhưng ít nhất không có ý nghĩa gì cho việc đóng gói) hoặc "bạn cũng có thể sử dụng chúng bên ngoài OOP", hoặc đại loại như thế.
SJuan76

2
Imo OO chỉ có một trụ cột và đó là: "Bang". Một khi bộ não của bạn nghĩ trong trạng thái bạn nhận được OO.
Pieter B

Câu trả lời:


40

Có phải sự kế thừa, đóng gói và đa hình không được coi là trụ cột của OOP bởi các lập trình viên Hoa Kỳ / Vương quốc Anh?

Chúng được coi là trụ cột bởi nhiều lập trình viên, và nhiều trường đại học dạy OO theo cách đó.

Thật không may, nó cũng là một cái nhìn thiển cận.

  • Kế thừa là một cơ chế được sử dụng để thực hiện OOP và có thể bị lạm dụng để không thực hiện OOP.
  • Encapsulation là một khái niệm, hữu ích cho lập trình của tất cả các loại, OOP và không.
  • Đa hình là một ... đặc điểm (?) Để mô tả cách tính toán hành xử. Có nhiều cách để đạt được tính đa hình, không phải tất cả đều là OO cụ thể.

OOP có rất ít nền tảng, vì trong thực tế, nó rất khái niệm: "Tiếp cận thiết kế chương trình của bạn bằng cách nghĩ về mọi thứ như các đối tượng - các gói dữ liệu và chức năng gắn kết."

Và trong khi thiết kế chương trình hiện đại có quan điểm kém khi thực hiện mọi thứ theo kiểu "hoàn toàn OO", hầu hết các lập trình viên lành nghề sẽ đồng ý rằng các nguyên tắc RẮN (hoặc một số tập hợp con) là ứng cử viên tốt hơn cho "trụ cột của Lập trình hướng đối tượng" (mặc dù họ áp dụng tốt cho không OOP). Chúng không hoạt động với các điều khoản này cả. Thay vào đó, họ sử dụng các khái niệm về các thực thể phần mềm (trong đó, các đối tượng là một), các giao diện (trong đó, C # / Java / v.v. interfacelà một), trừu tượng hóa và gõ phụ (trong đó, kế thừa là một dạng).


10
Câu trả lời cho một câu hỏi cơ bản không thể trả lời.
Robert Harvey

3
OOP có tồn tại không?
Tulains Córdova

5
Tôi sẽ lập luận rằng chỉ đóng gói là một "trụ cột" của OOP. Sự khác biệt lớn nhất giữa OOP và lập trình cấu trúc là ý tưởng rằng các đối tượng chứa mã dữ liệu, không chỉ là dữ liệu (ví dụ: cấu trúc C cổ điển). Hai khái niệm khác chủ yếu được sử dụng trong các ngôn ngữ OO, nhưng không bị hạn chế đối với OO hoặc được yêu cầu bởi nó.

3
@Snowman Encapsulation cũng không bị hạn chế đối với OOP. Mọi người thực hiện các kiểu dữ liệu trừu tượng trong C và các ngôn ngữ chức năng mọi lúc.
Doval

2
Và @ JörgWMittag đã có một câu trả lời tốt liên quan đến nhắn tin. Ý tưởng nhắn tin nhất thiết phải đóng gói. Thông điệp thường được chuyển đến một chức năng hoặc phương thức trên một đối tượng, sau đó hoạt động trên trạng thái được gói gọn trong đó. Điều đó không có nghĩa là các ngôn ngữ không phải OO cũng không thể có thông điệp hoặc đóng gói thông điệp, chỉ có điều đây là những ý tưởng nền tảng của OOP.

23

tl; dr: Bạn có thể có thừa kế mà không có OO, bạn có thể đóng gói mà không có OO, bạn có thể có đa hình mà không có OO, thậm chí bạn có thể có cả ba cùng một lúc mà không cần OO. Trên flipside, bạn có thể có OO mà không cần thừa kế. Thêm vào đó, có nhiều loại đóng gói khác nhau (định hướng ADT và OO), IOW không phải tất cả các đóng gói là OO.

Phiên bản dài:

Thuật ngữ "Lập trình hướng đối tượng" được phát minh bởi Alan Kay, vì vậy anh ta quyết định ý nghĩa của nó. Và ông định nghĩa nó theo cách này :

OOP với tôi có nghĩa là chỉ nhắn tin, duy trì và bảo vệ cục bộ và che giấu quá trình nhà nước, và ràng buộc cực kỳ muộn của tất cả mọi thứ.

Thực hiện khôn ngoan, tin nhắn là lời kêu gọi thủ tục cuối-bound, và nếu cuộc gọi thủ tục được cuối-bound, thì bạn không thể biết lúc thiết kế những gì bạn đang đi để gọi, vì vậy bạn không thể thực hiện bất kỳ giả định về đại diện cụ thể của nhà nước. Vì vậy, thực sự là về nhắn tin, ràng buộc muộn là việc thực hiện nhắn tin và đóng gói là hệ quả của nó.

Sau đó, ông đã làm rõ rằng " Ý tưởng lớn là" nhắn tin " ", và hối tiếc vì đã gọi nó là "hướng đối tượng" thay vì "hướng thông điệp", bởi vì thuật ngữ "hướng đối tượng" tập trung vào thứ không quan trọng (đối tượng ) và phân tâm từ những gì thực sự quan trọng (nhắn tin):

Chỉ cần một lời nhắc nhở nhẹ nhàng rằng tôi đã chịu một số đau đớn ở OOPSLA cuối cùng để cố gắng nhắc nhở mọi người rằng Smalltalk không chỉ KHÔNG phải là cú pháp của nó hay thư viện lớp, thậm chí nó không phải là về các lớp. Tôi xin lỗi vì từ lâu tôi đã đặt ra thuật ngữ "đối tượng" cho chủ đề này bởi vì nó khiến nhiều người tập trung vào ý tưởng ít hơn.

Ý tưởng lớn là "nhắn tin" - đó là tất cả những gì về hạt nhân của Smalltalk / Squeak (và đó là thứ chưa bao giờ hoàn thành trong giai đoạn Xerox PARC của chúng tôi). Người Nhật có một từ nhỏ - ma - cho "cái nằm ở giữa" - có lẽ tương đương với tiếng Anh gần nhất là "interstitial". Chìa khóa trong việc tạo ra các hệ thống tuyệt vời và có thể phát triển được nhiều hơn là thiết kế cách thức các mô-đun giao tiếp thay vì các đặc tính và hành vi bên trong của chúng. Hãy nghĩ về internet - để sống, nó (a) phải cho phép nhiều loại ý tưởng và hiện thực khác nhau vượt quá mọi tiêu chuẩn duy nhất và (b) để cho phép mức độ tương tác an toàn khác nhau giữa các ý tưởng này.

(Tất nhiên, ngày nay, hầu hết mọi người thậm chí không tập trung vào các đối tượng mà vào các lớp học, điều này thậm chí còn sai hơn.)

Nhắn tin là nền tảng cho OO, cả dưới dạng ẩn dụ và như một cơ chế.

Nếu bạn gửi tin nhắn cho ai đó, bạn sẽ không biết họ làm gì với nó. Điều duy nhất bạn có thể quan sát, là phản ứng của họ. Bạn không biết liệu họ có tự xử lý tin nhắn hay không (tức là nếu đối tượng có phương thức), nếu họ chuyển tiếp tin nhắn cho người khác (ủy quyền / ủy quyền), nếu họ thậm chí hiểu nó. Đó là tất cả những gì đóng gói, đó là tất cả những gì về OO. Bạn thậm chí không thể phân biệt một proxy với thực tế, miễn là nó đáp ứng như bạn mong đợi.

Một thuật ngữ "hiện đại" hơn cho "nhắn tin" là "gửi phương thức động" hoặc "gọi phương thức ảo", nhưng điều đó làm mất đi phép ẩn dụ và tập trung vào cơ chế.

Những điểm tương tự cũng được thực hiện trong Tìm hiểu về trừu tượng dữ liệu, được xem xét lại bởi William R. Cook và cũng là Đề xuất của ông về các định nghĩa hiện đại, đơn giản về "Đối tượng" và "Hướng đối tượng" .

Công văn năng động của các hoạt động là đặc tính thiết yếu của các đối tượng. Nó có nghĩa là hoạt động được gọi là một thuộc tính động của chính đối tượng. Các hoạt động không thể được xác định một cách tĩnh và nói chung không có cách nào để chính xác hoạt động nào sẽ được thực hiện để đáp ứng với một yêu cầu nhất định, ngoại trừ bằng cách chạy nó. Điều này hoàn toàn giống với các hàm hạng nhất, luôn được gửi động.

Trong Smalltalk-72, thậm chí không có bất kỳ đối tượng nào! Chỉ các dòng tin nhắn được phân tích cú pháp, viết lại và định tuyến lại. Các phương thức xuất hiện đầu tiên (các cách tiêu chuẩn để phân tích và định tuyến lại các luồng thông báo), các đối tượng đến sau (các nhóm phương thức chia sẻ một số trạng thái riêng tư). Kế thừa xuất hiện muộn hơn nhiều và các lớp chỉ được giới thiệu như một cách để hỗ trợ kế thừa. Nếu nhóm nghiên cứu của Kay đã biết về các nguyên mẫu, có lẽ họ sẽ không bao giờ giới thiệu các lớp học ở nơi đầu tiên.

Mỗi lập trình viên nên đọc về Tìm hiểu trừu tượng dữ liệu, xem lại . Nó giải thích chi tiết chính xác sự khác biệt giữa các Đối tượng và Kiểu dữ liệu trừu tượng. Anh ta đưa ra các ví dụ bằng cách sử dụng Java và điều đó cực kỳ phù hợp với câu hỏi này, bởi vì trong cả các ví dụ ADT các ví dụ về Đối tượng, anh ta sử dụng tính kế thừa, đóng gói và đa hình, nhưng chỉ một trong các ví dụ là hướng đối tượng! Nói cách khác: bạn có thể có sự kế thừa, đóng gói và đa hình, bạn thậm chí có thể có cả ba cùng một lúc mà vẫn không có OO.

Mặt khác, bạn có thể có OO mà không cần thừa kế. Giống như tôi đã gợi ý ở trên: các phiên bản gốc của Smalltalk (ngôn ngữ được thiết kế bởi Alan Kay, người phát minh ra thuật ngữ "Lập trình hướng đối tượng") không có sự kế thừa.

Cuối cùng, nhưng chắc chắn không kém phần quan trọng, Hiệp ước Orlando thảo luận về sự ủy thác như là một sự thay thế cho sự kế thừa và cách thức các hình thức ủy quyền và kế thừa khác nhau dẫn đến các điểm thiết kế khác nhau trong không gian thiết kế của các ngôn ngữ đối tượng. (Lưu ý rằng thực sự ngay cả trong các ngôn ngữ hỗ trợ kế thừa, như Java, mọi người thực sự được dạy để tránh điều đó, một lần nữa cho thấy rằng nó không cần thiết cho OO.)


Bạn có thể có "thừa kế", "đa hình" và "thừa kế" ... methinks có một lỗi đánh máy ở đâu đó :)
slebetman

1
Câu trả lời này khiến tôi ước chúng ta cũng có thể 'yêu thích' câu trả lời.
Chan-Ho Suh

Định nghĩa của Alan Kay đã lỗi thời. OO cần sự kế thừa và nếu bạn có thể thực hiện cả ràng buộc thời gian chạy và biên dịch thời gian như trong C ++, bạn cũng có được hiệu năng ngang bằng với C.
Erik Alapää

Không, định nghĩa của anh ấy là chính xác. Bạn hoàn toàn không cần thừa kế để trở thành OO. Ngôn ngữ nguyên mẫu không sử dụng tính kế thừa như C ++ và chúng vẫn là OO. Kế thừa chỉ được sử dụng để thực hiện tái sử dụng mã, đó thậm chí không phải là cách tốt nhất, có rất nhiều ngôn ngữ tốt hơn có mixin chẳng hạn. Nó cũng không liên quan gì đến ràng buộc, vì bạn có thể gửi động, thậm chí không có trong C ++ khi bạn có thể sử dụng các phương thức ảo. Hiệu suất không liên quan gì đến điều này, đó là những khái niệm cấp cao, chúng không có hiệu suất. Trên thực tế, bạn có thể triển khai tin nhắn chuyển qua C và là OO
Luiz Felipe
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.