Apakah ada bahasa OO tanpa warisan?

22

Selama ulasan kode hari ini, seorang rekan saya mengatakan sesuatu yang menarik:

prototypehanya berguna ketika Anda membutuhkan warisan - dan kapan warisan merupakan ide bagus ?

Saya memikirkan hal ini dan saya menyadari bahwa saya biasanya menggunakan warisan untuk menyiasati kode yang awalnya dirancang dengan buruk. Gaya OO modern lebih suka komposisi daripada warisan, tetapi saya tidak tahu bahasa apa pun yang telah membawa ini ke hati dan benar-benar menegakkannya .

Apakah ada bahasa pemrograman tujuan umum dengan kelas, objek, metode, antarmuka, dan sebagainya, yang melarang pewarisan berbasis kelas? (Jika ide seperti itu tidak masuk akal, mengapa tidak?)

Benjamin Hodgson
sumber
7
Rekan Anda telah menyesatkan Anda. Ini prototypejuga berguna ketika Anda memiliki metode dan properti publik yang harus dibagi di antara instance. Ini juga berguna karena memungkinkan Anda untuk benar menggunakan instanceofoperator dalam JavaScript: if (foo instanceof Foo) { ....
Greg Burghardt
2
Saya pikir kita harus membuat perbedaan antara pewarisan jenis, negara dan perilaku. Preferensi komposisi sangat umum di komunitas Jawa tetapi pada saat yang sama, jenis pewarisan (dan bahkan pewarisan berganda) banyak digunakan dan didorong ... dan direalisasikan menggunakan implementskata kunci dan antarmuka (sebagai lawan dari warisan negara dan perilaku yang diperkenalkan dengan penggunaan extendskata kunci pada kelas yang berisi implementasi apa pun).
toniedzwiedz
6
Memilih komposisi bukan berarti meninggalkan warisan sepenuhnya adalah ide yang bagus.
Caleb
5
lihat Java tanpa warisan implementasi : "Google go adalah contoh bahasa yang menghilangkan warisan implementasi saat menjadi OOP ..."
gnat
1
@GregBurghardt Hal yang sama dapat dilakukan dengan fungsi pabrik yang mengembalikan fungsi yang berisi objek (menyimpan data pribadi di penutupan). new, thisdan prototypeterlalu banyak ladang ranjau untuk penggunaan umum IMO.
Benjamin Hodgson

Jawaban:

18

Mengesampingkan pertanyaan tentang definisi pemrograman berorientasi objek pertanyaan menjadi salah satu "apakah ada bahasa yang hanya menggunakan komposisi dan tidak memiliki alat untuk pewarisan?"

Jawabannya cukup sederhana "ya". Pada akhirnya, tidak ada cara untuk melakukan warisan seperti yang dipikirkan orang secara klasik. Satu dapat tertanam objek di objek lain dan memperluas objek itu. Dari Object 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()
}

Anda memiliki struct orang yang memiliki Nama yang merupakan String. Ini memiliki fungsi publik yang disebut Intro yang mengembalikan nama. Struct Wanita juga memiliki fungsi untuk Intro yang mengakses strut yang tertanam di dalamnya. Dan dengan demikian seseorang dapat memenuhi niat pewarisan dengan menggunakan komposisi saja.

Lebih lanjut tentang ini dapat dilihat di GoLang Tutorials: Inheritance dan subclassing di Go - atau yang hampir mirip .

Jadi ya, adalah mungkin untuk memiliki bahasa OO tanpa warisan, dan memang ada.

Dalam go go ini dikenal sebagai embedding dan memberi struktur penutup kemampuan untuk mengakses bidang dan fungsi yang tertanam seolah-olah memilikinya juga - tetapi ini bukan subkelas. Filosofi desain dapat ditemukan di Go FAQ: Mengapa tidak ada pewarisan tipe?


sumber
Orang juga bisa berkomentar tentang penggunaan typedefdan structdalam C ...
cwallenpoole
@cwallenpoole memang ada ide serupa di sana, meskipun saya akan ragu untuk menyebut C bahasa yang berorientasi objek.
Saya tidak tahu. Saya akan mengakui kenyataan bahwa Anda tidak dapat membuat objek dengan fungsi yang dilampirkan tidak bekerja melawannya, tetapi tanpa warisan, OOP kehilangan banyak rasanya.
cwallenpoole
@cwallenpoole dan kita mulai mendefinisikan apa warisan dan orientasi objek. Tapi itu adalah mungkin, hanya cara berpikir yang berbeda tentang masalah ini. Masalahnya adalah bahwa warisan adalah cara kebanyakan C + + dan programmer Java memikirkan ekstensi ... tetapi ada model lain. Ekstensi tanpa warisan: 1 , 2 , 3 adalah bacaan yang baik.
Tautan ke "Object Desoriented Language" saat ini terjebak dalam redirect loop, tetapi saya menemukan artikel di sini: github.com/nu7hatch/areyoufuckingcoding.me/blob/master/content/… . Terima kasih!
Matt Browne
7

Apakah ada bahasa pemrograman tujuan umum dengan kelas, objek, metode, antarmuka, dan sebagainya, yang melarang pewarisan berbasis kelas?

Ini sangat mirip dengan deskripsi VBA - Visual Basic for Applications, tertanam di Microsoft Office dan host berkemampuan VBA lainnya (mis. AutoCAD, Sage 300 ERP, dll.), Atau bahkan VB6. "A" dari "Basic" adalah singkatan dari "All-purpose", jadi ada bagian "general-purpose".

VB6 / VBA memiliki kelas (dan karenanya objek), metode, dan antarmuka - Anda dapat mendefinisikan ISomethingantarmuka dalam modul kelas seperti ini:

Option Explicit

Public Sub DoSomething()
End Sub

Dan kemudian memiliki kelas lain yang melakukan ini:

Option Explicit
Implements ISomething

Private Sub ISomething_DoSomething()
    'implementation here
End Sub

Kelas semacam itu, yang tidak memperlihatkan anggota publik, hanya dapat diakses melalui ISomethingantarmuka - dan mungkin ada puluhan implementasi yang berbeda di ISomethingluar sana, sehingga kode OOP VBA sangat mampu melakukan polimorfisme, dan sangat legal untuk kelas tertentu untuk mengimplementasikan beberapa antarmuka juga.

VB6 / VBA tidak memungkinkan pewarisan kelas , jadi Anda tidak bisa mewarisi implementasi dari tipe lain, hanya antarmuka-nya. Sekarang, apakah ini kecelakaan, cacat desain, jenius, atau kekeliruan besar terbuka untuk diperdebatkan; tidak jelas apakah VB6 / VBA membawa ini ke hati , tetapi yang paling pasti menegakkannya .

Jika Go tidak melakukan warisan kelas dan tetap merupakan bahasa OOP , maka saya tidak mengerti mengapa VB6 / VBA tidak dapat dianggap sebagai bahasa OOP juga.</PreemptiveResponseToVBAHatersThatWillSayItIsNotAnOOPLanguage>

Mathieu Guindon
sumber
1
Agar adil, OP bertanya tentang bahasa modern . =;) -
RubberDuck
@RubberDuck #burn!
Mathieu Guindon
0

Anda dapat membuat kompilator menegakkan pewarisan selektif melalui penggunaan teknik privat / terproteksi, dan melalui modern "PImpl", atau "Implementasi Privat".

Banyak API mengekspos hanya komponen-komponen yang Anda inginkan agar diwarisi oleh pengguna, dan menyembunyikan yang lainnya di kelas implementasi yang terpisah. Jadi, Anda bisa menulis kelas yang antarmuka publiknya, pada kenyataannya, tidak dapat diraih, hanya dapat digunakan melalui komposisi objek, dan kompiler-diberlakukan. Ini sering merupakan praktik yang baik, ketika menggunakan kompiler untuk menegakkan maksud dari perangkat lunak.

Pencarian cepat untuk fungsi anggota pribadi di javascript menunjukkan ada prinsip yang serupa, meskipun siapa pun dapat melihat kode Anda jika mereka dapat menggunakannya: http://www.crockford.com/javascript/private.html

Ruan Caiman
sumber