OK, jadi mudah-mudahan ini adalah pertanyaan yang cukup subjektif untuk Programmer, tetapi begini saja. Saya terus memperluas pengetahuan saya tentang bahasa dan praktik rekayasa perangkat lunak ... dan saya telah mengalami sesuatu yang tidak masuk akal bagi saya sama sekali.
Dalam C ++, deklarasi kelas menyertakan private:
metode dan parameter dalam file header, yang, secara teoritis, adalah apa yang Anda berikan kepada pengguna untuk disertakan jika Anda menjadikannya lib.
Di Objective-C, @interface
lakukan hal yang hampir sama, memaksa Anda untuk membuat daftar anggota pribadi Anda (setidaknya, ada cara untuk mendapatkan metode pribadi dalam file implementasi).
Dari apa yang dapat saya katakan, Java dan C # memungkinkan Anda untuk menyediakan antarmuka / protokol yang dapat mendeklarasikan semua properti / metode yang dapat diakses publik dan memberi koder kemampuan untuk menyembunyikan semua detail implementasi dalam file implementasi.
Mengapa? Enkapsulasi adalah salah satu prinsip utama OOP, mengapa C ++ dan Obj-C tidak memiliki kemampuan dasar ini? Apakah ada semacam praktik kerja terbaik untuk Obj-C atau C ++ yang menyembunyikan semua implementasi?
Terima kasih,
sumber
Jawaban:
Pertanyaannya adalah apakah kompiler perlu tahu seberapa besar suatu objek. Jika demikian, maka kompiler harus tahu tentang anggota pribadi untuk menghitungnya.
Di Jawa, ada tipe dan objek primitif, dan semua objek dialokasikan secara terpisah, dan variabel yang mengandungnya benar-benar pointer. Oleh karena itu, karena pointer adalah objek ukuran tetap, kompiler tahu seberapa besar hal yang diwakili variabel, tanpa mengetahui ukuran sebenarnya dari objek yang diarahkan ke. Konstruktor menangani semua itu.
Di C ++, dimungkinkan untuk memiliki objek yang diwakili secara lokal atau di heap. Oleh karena itu, kompiler perlu mengetahui seberapa besar suatu objek, sehingga dapat mengalokasikan variabel atau array lokal.
Kadang-kadang diinginkan untuk membagi fungsionalitas kelas menjadi antarmuka publik dan semua hal pribadi lainnya, dan di situlah teknik PIMPL (Pointer ke IMPLementation) masuk. Kelas akan memiliki pointer ke kelas implementasi pribadi, dan metode kelas publik dapat memanggil bahwa.
sumber
Karena desain C ++, untuk membuat objek pada stack, kompiler harus tahu seberapa besar itu. Untuk melakukan ini, semua bidang harus ada dalam file header, karena hanya itu yang dapat dilihat oleh kompiler ketika header disertakan.
Misalnya jika Anda mendefinisikan kelas
lalu
sizeof(Foo)
adalahsizeof(a) + sizeof(b)
. Jika ada beberapa mekanisme untuk memisahkan bidang pribadi, maka header mungkin berisidengan
sizeof(Foo) = sizeof(a) + ???
.Jika Anda ingin benar-benar menyembunyikan data pribadi, coba idiom pimpl, dengan
di header dan definisi untuk
FooImpl
hanya diFoo
's file implementasi.sumber
Ini semua bermuara pada pilihan desain.
Jika Anda benar-benar ingin menyembunyikan detail implementasi privat dari kelas C ++ atau Objective-C, maka Anda menyediakan satu atau lebih antarmuka yang didukung oleh kelas (kelas virtual murni C ++, Objective-C @protocol) dan / atau Anda membuat kelas mampu membangun sendiri dengan menyediakan metode pabrik statis atau objek pabrik kelas.
Alasan bahwa variabel pribadi diekspos dalam file header / deklarasi kelas / antarmuka @ adalah bahwa konsumen kelas Anda mungkin perlu membuat instance baru dan dan
new MyClass()
atau[[MyClass alloc]init]
dalam kode klien perlu kompiler untuk memahami seberapa besar MyClass objek untuk melakukan alokasi.Java dan C # juga memiliki variabel pribadi mereka yang terperinci di kelas - mereka tidak terkecuali untuk ini, tetapi IMO paradigma antarmuka jauh lebih umum dengan bahasa-bahasa tersebut. Anda mungkin tidak memiliki kode sumber di setiap kasus, tetapi ada cukup metadata dalam kode / byte yang dikompilasi untuk menyimpulkan informasi ini. Karena C ++ dan Objective-C tidak memiliki metadata ini, satu-satunya pilihan adalah detail sebenarnya dari antarmuka kelas / @. Di dunia C ++ COM, Anda tidak mengekspos variabel pribadi dari kelas apa pun yang dapat menyediakan file header - karena kelasnya adalah virtual murni. Objek pabrik kelas terdaftar untuk membuat instance aktual juga, dan ada beberapa metadata dalam berbagai bentuk.
Dalam C ++ dan Objective-C, lebih sedikit pekerjaan untuk membagikan file header dibandingkan dengan menulis dan memelihara file antarmuka / protokol @ tambahan. Ini adalah salah satu alasan mengapa Anda sering melihat implementasi pribadi begitu terbuka.
Alasan lain dalam C ++ adalah templat - kompiler perlu mengetahui detail kelas untuk menghasilkan versi kelas yang khusus untuk parameter yang disediakan. Ukuran anggota kelas akan bervariasi dengan parameterisasi, sehingga perlu memiliki informasi ini.
sumber