Có ngôn ngữ OO nào không có sự kế thừa không?


22

Trong buổi đánh giá mã ngày hôm nay, một đồng nghiệp của tôi đã nói một điều thú vị:

prototypechỉ hữu ích khi bạn cần thừa kế - và khi nào thì thừa kế bao giờ là một ý tưởng tốt ?

Tôi đã nghĩ về điều này và tôi nhận ra rằng tôi thường sử dụng tính kế thừa để đi vòng quanh mã được thiết kế tồi ngay từ đầu. Phong cách OO hiện đại thích sáng tác hơn sự kế thừa, nhưng tôi không biết bất kỳ ngôn ngữ nào đã làm điều này thành trái tim và thực sự thi hành nó.

Có bất kỳ ngôn ngữ lập trình đa mục đích nào với các lớp, đối tượng, phương thức, giao diện, v.v., không cho phép kế thừa dựa trên lớp không? (Nếu một ý tưởng như vậy không có ý nghĩa, tại sao không?)


7
Đồng nghiệp của bạn đã dẫn bạn lạc lối. Điều prototypenày cũng hữu ích khi bạn có các phương thức và thuộc tính công khai nên được chia sẻ giữa các trường hợp. Nó cũng hữu ích vì nó cho phép bạn sử dụng đúng instanceoftoán tử trong JavaScript : if (foo instanceof Foo) { ....
Greg Burghardt

2
Tôi nghĩ chúng ta nên phân biệt giữa sự kế thừa của loại hình, trạng thái và hành vi. Sở thích sáng tác rất phổ biến trong cộng đồng Java nhưng đồng thời, tính kế thừa (và thậm chí nhiều kiểu thừa kế) được sử dụng và khuyến khích rộng rãi ... và nhận ra bằng cách sử dụng implementstừ khóa và giao diện (trái ngược với sự kế thừa của trạng thái và hành vi được giới thiệu với việc sử dụng extendstừ khóa trên các lớp có chứa bất kỳ triển khai nào).
toniedzwiedz

6
Thành phần ưu tiên không có nghĩa là hoàn toàn từ bỏ thừa kế là một ý tưởng tốt.
Caleb

5
xem Java mà không có sự kế thừa triển khai : "Google go là một ví dụ về ngôn ngữ không có sự kế thừa thực hiện trong khi là OOP ..."
gnat

1
@GregBurghardt Điều tương tự có thể được thực hiện với hàm xuất xưởng trả về một đối tượng chứa các hàm (lưu trữ dữ liệu riêng tư trong bao đóng). new, thisprototypetất cả đều quá nhiều của một bãi mìn để sử dụng chung IMO.
Benjamin Hodgson

Câu trả lời:


18

Đặt sang một bên câu hỏi về định nghĩa lập trình hướng đối tượng , câu hỏi trở thành một trong những "ngôn ngữ chỉ sử dụng thành phần và không có công cụ để kế thừa?"

Câu trả lời cho điều này khá đơn giản là "có". Trong khi đó, không có cách nào để làm thừa kế như người ta nghĩ về nó. Người ta có thể nhúng một đối tượng trong một đối tượng khác và mở rộng đối tượng đó. Từ đối tượng Desoriented Language ( github mirror ):

type Person struct {
        Name string
}

func (p *Person) Intro() string {
        return p.Name
}

type Woman struct {
        Person
}

func (w *Woman) Intro() string {
        return "Mrs. " + w.Person.Intro()
}

Bạn đã có một cấu trúc người có Tên là Chuỗi. Nó có một chức năng công khai gọi là Intro trả về tên. Cấu trúc Woman cũng có một chức năng cho Giới thiệu truy cập thanh chống được nhúng trong nó. Và do đó, người ta có thể thực hiện ý định thừa kế bằng cách chỉ sử dụng thành phần.

Thông tin thêm về điều này có thể được nhìn thấy tại Hướng dẫn của GoLang: Kế thừa và phân lớp trong Go - hoặc gần giống với nó .

Vì vậy, có, có thể có một ngôn ngữ OO mà không cần kế thừa, và một ngôn ngữ tồn tại.

Bên trong, điều này được gọi là nhúng và cung cấp cho các cấu trúc kèm theo khả năng truy cập các trường và chức năng nhúng như thể nó cũng có chúng - nhưng nó không phải là một lớp con. Triết lý thiết kế có thể được tìm thấy trong Câu hỏi thường gặp về Go: Tại sao không có kiểu thừa kế?


Người ta cũng có thể nhận xét về việc sử dụng typedefstructtrong C ...
cwallenpoole

@cwallenpoole thực sự có những ý tưởng tương tự ở đó, mặc dù tôi rất ngại gọi C là ngôn ngữ hướng đối tượng.

Tôi không biết. Tôi sẽ thừa nhận thực tế rằng bạn không thể tạo các đối tượng có chức năng kèm theo sẽ chống lại nó, nhưng không có sự kế thừa, OOP mất đi nhiều hương vị của nó.
cwallenpoole

@cwallenpoole và chúng tôi bắt đầu xác định kế thừa là gì và hướng đối tượng. Nhưng nó có thể, nó chỉ là một cách khác nhau suy nghĩ về vấn đề này. Vấn đề là sự kế thừa là cách mà hầu hết các lập trình viên C ++ và Java nghĩ về phần mở rộng ... nhưng có những mô hình khác. Gia hạn không kế thừa: 1 , 2 , 3 là những bài đọc tốt.

Hiện tại, liên kết đến "Ngôn ngữ mong muốn đối tượng" đang bị kẹt trong một vòng lặp chuyển hướng, nhưng tôi đã tìm thấy bài viết ở đây: github.com/nu7hatch/areyoufuckingcoding.me/blob/master/content/ . Cảm ơn!
Matt Browne

7

Có bất kỳ ngôn ngữ lập trình đa mục đích nào với các lớp, đối tượng, phương thức, giao diện, v.v., không cho phép kế thừa dựa trên lớp không?

Điều này đọc rất giống với mô tả về VBA - Visual Basic cho Ứng dụng, được nhúng trong Microsoft Office và các máy chủ hỗ trợ VBA khác (ví dụ: AutoCAD, Sage 300 ERP, v.v.) hoặc thậm chí VB6. "A" của "Cơ bản" là viết tắt của "Tất cả mục đích", vì vậy có phần "mục đích chung".

VB6 / VBA có các lớp (và do đó là các đối tượng), các phương thức và giao diện - bạn có thể định nghĩa một ISomethinggiao diện trong một mô-đun lớp như thế này:

Option Explicit

Public Sub DoSomething()
End Sub

Và sau đó có một lớp khác thực hiện điều này:

Option Explicit
Implements ISomething

Private Sub ISomething_DoSomething()
    'implementation here
End Sub

Một lớp như vậy, không có thành viên nào, chỉ có thể được truy cập qua ISomethinggiao diện của nó - và rất có thể có hàng tá các triển khai khác nhau ISomethingngoài đó, vì vậy mã OOP VBA hoàn toàn có khả năng đa hình, và nó hoàn toàn hợp pháp cho một lớp nhất định để thực hiện nhiều giao diện, quá.

Tuy nhiên, VB6 / VBA không cho phép kế thừa lớp , do đó bạn không thể kế thừa triển khai từ loại khác, chỉ giao diện của nó. Bây giờ, cho dù đây là một tai nạn, một lỗi thiết kế, đột quỵ của thiên tài hay một sự giám sát xấu xí khổng lồ đang mở ra cho cuộc tranh luận; Không rõ liệu VB6 / VBA có làm được điều này hay không , nhưng chắc chắn nó sẽ thực thi nó.

Nếu Go không thực hiện kế thừa lớp và dù sao cũng là ngôn ngữ OOP , thì tôi không hiểu tại sao VB6 / VBA cũng không thể được coi là ngôn ngữ OOP.</PreemptiveResponseToVBAHatersThatWillSayItIsNotAnOOPLanguage>


1
Để công bằng, OP đã hỏi về các ngôn ngữ hiện đại . =;) -
RubberDuck

@RubberDuck #burn!
Mathieu Guindon

0

Bạn có thể làm cho trình biên dịch thực thi kế thừa chọn lọc thông qua việc sử dụng riêng tư / được bảo vệ và thông qua việc sử dụng các kỹ thuật "PImpl" hoặc "Thực hiện riêng tư" hiện đại.

Nhiều API chỉ hiển thị những thành phần mà bạn muốn người dùng kế thừa và ẩn phần còn lại trong một lớp triển khai riêng. Vì vậy, bạn có thể viết các lớp có giao diện công khai, trên thực tế, không thể quản lý được, chỉ có thể sử dụng thông qua thành phần đối tượng và trình biên dịch được thi hành. Điều này thường là thực hành tốt, khi nó sử dụng trình biên dịch để thực thi ý định của phần mềm.

Tìm kiếm nhanh các chức năng thành viên riêng tư trong javascript cho thấy có một nguyên tắc tương tự, mặc dù bất kỳ ai cũng có thể thấy mã của bạn nếu họ có thể sử dụng nó: http://www.crockford.com/javascript/private.html

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.