Mengapa C tidak dianggap sebagai bahasa 'berorientasi objek'?

92

Tampaknya C memiliki objek semu sendiri seperti 'struct' yang dapat dianggap sebagai objek (dengan cara tingkat tinggi yang biasanya kita pikirkan).

Dan juga, file C sendiri pada dasarnya terpisah "modul", kan? Lalu bukankah modul juga seperti 'objek'? Saya bingung mengapa C, yang tampaknya sangat mirip dengan C ++, dianggap sebagai bahasa "prosedural" tingkat rendah di mana C ++ adalah tingkat tinggi "berorientasi objek"

* edit: (klarifikasi) mengapa dan di mana, apakah garis digambar, untuk apa 'objek' itu, dan bukan?

Dark Templar
sumber
40
Semua - mengapa suara turun? Ini pertanyaan mendasar tapi bukan yang buruk.
Jon Hopkins
7
Anda dapat menggunakan prinsip-prinsip OO secara efektif dalam C (dan orang-orang yang menulis kode C yang baik biasanya melakukannya), tetapi bahasa ini tidak dibangun dengan mudah, karena banyak bahasa yang lebih baru.
asveikau
5
C hanya memiliki pendekatan yang berbeda, lebih sederhana, dan (sejujurnya) lebih baik didefinisikan (setidaknya di antara komunitas open-source) untuk abstraksi data. C ++ cenderung menjadi pembangkit tenaga listrik abstraksi dan memungkinkan banyak hal besar, tetapi datang dengan biaya karena harus memahami bagaimana [tidak] menggunakannya dengan benar, yang, lebih sering daripada tidak, cukup hilang dalam program umum. Lihat jawaban lengkap saya untuk lebih jelasnya.
Yam Marcovic
1
Singkatnya: Structs tidak dapat memiliki metode. (Pointer ke fungsi tidak cukup memotongnya).
SF.
1
Dimungkinkan untuk melakukan pemrograman berbasis objek dalam C, dengan beberapa kesulitan. Tapi itu tidak membuatnya berorientasi objek .
Wedge

Jawaban:

101

Tampaknya C memiliki objek semu sendiri seperti 'struct' yang dapat dianggap sebagai objek

Mari bersama-sama Anda dan saya membaca halaman Wikipedia tentang pemrograman berorientasi objek dan memeriksa fitur struct C-style yang sesuai dengan apa yang secara tradisional dianggap sebagai gaya berorientasi objek:

(OOP) adalah paradigma pemrograman menggunakan "objek" - struktur data yang terdiri dari bidang data dan metode bersama dengan interaksinya

Apakah C struct terdiri dari bidang dan metode bersama dengan interaksinya ? Tidak.

Teknik pemrograman dapat mencakup fitur-fitur seperti abstraksi data, enkapsulasi, pengiriman pesan, modularitas, polimorfisme, dan pewarisan.

Apakah C struct melakukan hal-hal ini dengan cara "kelas satu"? Tidak. Bahasa ini menentang Anda di setiap langkah.

pendekatan berorientasi objek mendorong programmer untuk menempatkan data di tempat yang tidak dapat diakses langsung oleh program lainnya

Apakah C struct melakukan ini? Tidak.

Program berorientasi objek biasanya akan berisi berbagai jenis objek, masing-masing jenis sesuai dengan jenis data kompleks tertentu yang akan dikelola atau mungkin dengan objek atau konsep dunia nyata

Apakah C struct melakukan ini? Iya.

Objek dapat dianggap sebagai membungkus data mereka dalam satu set fungsi yang dirancang untuk memastikan bahwa data digunakan dengan tepat

Tidak.

setiap objek mampu menerima pesan, memproses data, dan mengirim pesan ke objek lain

Bisakah struct sendiri mengirim dan menerima pesan? Tidak. Bisakah data diproses? Tidak.

Struktur data OOP cenderung "membawa operator mereka sendiri bersama mereka"

Apakah ini terjadi di C? Tidak.

Pengiriman dinamis ... Enkripsi Abstraksi

Apakah ada fitur C struct ini? Tidak.

Menurut Anda karakteristik struct mana yang menurut Anda "berorientasi objek"? Karena saya tidak dapat menemukan apa pun selain fakta bahwa struct mendefinisikan jenis .

Sekarang, tentu saja Anda dapat membuat struct yang memiliki bidang yang menjadi penunjuk fungsi. Anda bisa membuat struct memiliki bidang yang pointer ke array pointer fungsi, sesuai dengan tabel metode virtual. Dan seterusnya. Anda tentu saja dapat meniru C ++ dalam C. Tapi itu adalah cara yang sangat non-idiomatis untuk memprogram dalam C; Anda akan lebih baik hanya menggunakan C ++.

Dan juga, file C sendiri pada dasarnya terpisah "modul", kan? Lalu bukankah modul juga seperti 'objek'?

Sekali lagi, karakteristik modul apa yang Anda pikirkan yang membuatnya bertindak seperti objek? Apakah modul mendukung abstraksi, enkapsulasi, pengiriman pesan, modularitas, polimorfisme, dan pewarisan?

Abstraksi dan enkapsulasi cukup lemah. Jelas modul bersifat modular; itu sebabnya mereka disebut modul. Perpesanan? Hanya dalam arti bahwa panggilan metode adalah pesan dan modul dapat berisi metode. Polimorfisme? Nggak. Warisan? Nggak. Modul adalah kandidat yang cukup lemah untuk "objek".

Eric Lippert
sumber
15
Saya tidak setuju bahwa "meniru C ++" (istilah Anda) tidak idiomatis C. Satu contoh counter adalah bagaimana kernel OS biasanya mengimplementasikan operasi file - ambil Linux sebagai contoh, di mana Anda memiliki struct yang penuh dengan pointer fungsi. Mereka mungkin agak idiom "khusus-domain" (dibatasi untuk menulis driver pada * nix, katakanlah), tetapi mereka dikenali dan melakukan pekerjaan cukup bersih untuk beberapa tujuan. Ada juga beberapa contoh pustaka mode pengguna yang melakukan beberapa gagasan tentang OO dengan cukup baik; ambil Gtk + dan pustaka yang bergantung padanya. Sebut saja itu hacky dan Anda mungkin benar, tetapi ini tidak buruk untuk dikerjakan
asveikau
5
@asveikau: Bukankah gagasan bahwa praktik itu tidak biasa (bahkan jika tidak pernah terjadi) dan "peretasan" berarti bahwa, menurut definisi, bukan idiomatik?
Adam Robinson
19
@asveikau: Tentu, ada hal-hal yang dapat Anda lakukan untuk membuat program C lebih bergaya OO. Tetapi seperti yang Anda katakan, dibutuhkan disiplin untuk melakukannya; fitur bahasa itu sendiri tidak secara alami membawa Anda ke arah enkapsulasi, polimorfisme, warisan kelas, dan sebagainya. Sebaliknya, pengembang dapat memaksakan pola itu pada bahasa. Itu tidak berarti bahwa struct secara logis sama dengan objek. Heck, Anda dapat memprogram dalam gaya OO di Lisp juga, tetapi itu tidak berarti bahwa sel kontra adalah objek.
Eric Lippert
3
@asveikau, bolehkah saya menyarankan bahwa (mis) interpretasi Anda tentang "idiom" sebagai "milik sendiri" agak ... idiosyncratic? :)
Benjol
8
@ BillK: Structs tidak dapat berisi kode dalam C. Structs dapat berisi pointer fungsi , yang merupakan data . Pointer fungsi bukan kode . Kode adalah artefak tekstual yang dibuat oleh seorang programmer.
Eric Lippert
46

Kata kuncinya adalah "berorientasi", bukan "objek". Bahkan kode C ++ yang menggunakan objek tetapi menggunakannya seperti struct tidak berorientasi objek .

C dan C ++ keduanya dapat melakukan OOP (selain dari tidak ada kontrol akses di C), tetapi sintaks untuk melakukannya di C tidak nyaman (untuk sedikitnya), sedangkan sintaks di C ++ membuatnya sangat mengundang. C berorientasi pada prosedural, sedangkan C ++ berorientasi pada objek, meskipun kemampuan inti hampir identik dalam hal itu.

Kode yang menggunakan objek untuk mengimplementasikan desain yang hanya dapat dilakukan dengan objek (biasanya berarti mengambil keuntungan dari polimorfisme) adalah kode berorientasi objek. Kode yang menggunakan objek sedikit lebih banyak daripada kantung data, bahkan menggunakan pewarisan dalam bahasa berorientasi objek, sebenarnya hanya kode prosedural yang lebih rumit dari yang seharusnya. Kode dalam C yang menggunakan pointer fungsi yang diubah pada saat runtime dengan struct penuh data agak melakukan polimorfisme, dan bisa dikatakan "berorientasi objek", bahkan dalam bahasa yang berorientasi prosedural.

Kylben
sumber
2
+1 Untuk menunjuk C kita bisa OO. Ini tidak nyaman, tetapi bisa dilakukan.
dietbuddha
Lebih mudah untuk membuat objek di VBA, tapi saya tidak akan menganggapnya sebagai objek 'berorientasi' juga.
JeffO
VBA saya sebut "berbasis objek". Ini menggunakan objek, tetapi tidak secara polimorfik, dan dalam sedikit pekerjaan yang telah saya lakukan di dalamnya, saya tidak yakin Anda bahkan dapat melakukan polimorfisme apa pun jenis kode akrobat yang Anda coba. Ini pada dasarnya adalah bahasa prosedural dengan enkapsulasi.
kylben
2
Sebagian besar bahasa dapat bertindak sebagai OO, fungsional atau gaya bahasa lainnya. perbedaannya adalah "Berorientasi" dan saya tidak pernah mendengarnya seperti itu sebelumnya. Saya berharap saya bisa memilih ini 3 kali dan menerimanya, itu jawaban yang tepat.
Bill K
1
@ kylben Tidak akan terlalu sulit untuk menyimpan kode SQL di tabel lalu ekstrak dan jalankan (membuat tabel objek Anda) Ini akan menjadi percobaan yang menarik. Sebenarnya ini sedikit menggoda ...
Bill K
19

Berdasarkan kepala sekolah tingkat tertinggi:

Objek adalah enkapsulasi data dan perilaku dalam cara yang saling terkait sehingga mereka beroperasi secara keseluruhan yang dapat instantiate beberapa kali dan bekerja sebagai kotak hitam jika Anda tahu antarmuka eksternal.

Struct berisi data tetapi tidak ada perilaku dan karenanya tidak dapat dianggap objek.

Modul berisi perilaku dan data tetapi tidak dienkapsulasi sedemikian rupa sehingga keduanya terkait dan tentu saja tidak dapat dipakai berulang kali.

Dan itu sebelum Anda mendapatkan warisan dan polimorfisme ...

Jon Hopkins
sumber
Kenapa perilaku dan data dalam modul tidak terkait? Bukankah fungsi anggota pada dasarnya adalah 'perilaku' pada data yang ada di dalam modul?
Dark Templar
4
Masalahnya adalah bahwa mereka tidak dienkapsulasi, bukan bahwa mereka tidak terkait.
Eoin Carroll
Sebenarnya objek dipusatkan terutama di sekitar perilaku , bukan data. Data adalah / harus menjadi warga negara kelas dua di OOP. Structs, sebaliknya dipusatkan di sekitar data dan tidak memiliki perilaku.
Sklivvz
1
@Dark Templar - Apa yang dikatakan Eoin ... Itu adalah sifat dari hubungan itu. Saya bisa melihat dari mana Anda berasal - Anda tentu bisa menggunakan Structs dalam sebuah modul sedemikian rupa sehingga ia meniru beberapa elemen yang sangat mendasar dari OO tetapi banyak dari apa yang akan Anda lakukan bergantung pada programmer yang menempel pada set. aturan yang dipaksakan sendiri daripada memiliki bahasa menegakkannya. Dan mengapa Anda repot-repot? Anda tidak mendapatkan manfaat OO - tidak ada warisan misalnya - dan Anda membatasi diri.
Jon Hopkins
Ini adalah jawaban yang lebih baik daripada yang ditandai benar.
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz
6

"struct" hanya data. Tes cepat dan kotor yang biasa dari "orientasi objek" adalah: "Apakah ada struktur yang memungkinkan kode dan data untuk dienkapsulasi sebagai satu unit?". C gagal, dan karenanya prosedural. C ++ melewati tes itu.

Brian Knoblauch
sumber
6
Ada beberapa solusi, struct dapat memiliki pointer fungsi statis ke fungsi anggota. Mereka akan membutuhkan thispointer eksplisit , tetapi dalam hal ini, data dan sarana untuk memproses data akan dienkapsulasi di dalam struktur.
Coder
@ Brian Knoblauch: tetapi bukankah file C itu sendiri merupakan enkapsulasi data dan kode ??
Dark Templar
@DarkTemplar Dalam arti tertentu, ya, tetapi kecuali jika Anda berhasil membuat unit terjemahan, kompilasi dan muat ke dalam proses yang sedang berjalan pada saat runtime, ini tidak baik bagi Anda.
unit terjemahan? >. <
Dark Templar
@Dark Templar: Sebuah unit terjemahan adalah sumber file ditambah apapun #included ke dalamnya, dan minus apapun dihapus dengan tidak kondisional termasuk ( #if, #ifdef, dan sejenisnya).
David Thornley
5

C, seperti halnya C ++, memiliki kemampuan menyediakan Abstraksi Data , yang merupakan salah satu ungkapan dari paradigma pemrograman berorientasi objek yang ada sebelumnya.

  • C struct dapat memiliki data (dan itulah tujuan utamanya)
  • C struct juga dapat mendefinisikan pointer fungsi sebagai data
  • C struct dapat dan sering memiliki satu set fungsi yang terkait dengan mereka, seperti metode, hanya ini pointer tidak lulus implisit, tetapi Anda harus menentukan secara eksplisit sebagai argumen pertama untuk setiap metode yang dirancang untuk menangani struct ditentukan. C ++ melakukan ini secara otomatis untuk Anda, baik ketika Anda mendefinisikan dan memanggil metode kelas / struct.

OOP dalam C ++ memperluas sarana untuk data abstrak. Beberapa mengatakan itu berbahaya , sementara yang lain menganggapnya sebagai alat yang baik bila digunakan dengan benar.

  • C ++ membuat pointer ini tersirat dengan tidak mengharuskan pengguna untuk meneruskannya ke "metode kelas / struct" selama jenisnya dapat (setidaknya sebagian) diidentifikasi.
  • C ++ memungkinkan Anda membatasi akses ke metode tertentu (fungsi kelas), dan karenanya memungkinkan lebih banyak "pemrograman defensif" atau "pemeriksaan-idiot".
  • C ++ mendorong abstraksi dengan memberikan keamanan jenis yang lebih kuat dengan memperkenalkan
    1. The baru Operator bukannya malloc + cor
    2. Templat alih-alih batal pointer
    3. Fungsi sebaris menerima nilai yang diketik alih-alih makro
    4. Dibangun dalam Polimorfisme yang tidak harus Anda implementasikan sendiri, yang memungkinkan Anda membuat hierarki abstraksi , kontrak , dan spesialisasi .

Namun, Anda akan menemukan banyak C "peretas" berkhotbah tentang bagaimana C mampu melakukan abstraksi dengan jumlah yang tepat dan bagaimana overhead yang dibuat oleh C ++ hanya mengalihkan mereka dari penyelesaian masalah yang sebenarnya.

Model pemrograman abstrak yang tidak efisien di mana dua tahun kemudian Anda melihat bahwa beberapa abstraksi tidak terlalu efisien, tetapi sekarang semua kode Anda tergantung pada semua model objek yang bagus di sekitarnya, dan Anda tidak dapat memperbaikinya tanpa menulis ulang aplikasi Anda. - Linus Torvalds

Yang lain cenderung melihatnya dengan cara yang lebih seimbang, menerima baik kelebihan maupun kekurangannya.

C memudahkan Anda menembak diri sendiri di kaki; C ++ membuatnya lebih sulit, tetapi ketika Anda melakukannya, pukulan seluruh kaki Anda akan terhenti. - Bjarne Stroustrup

Yam Marcovic
sumber
2

Anda perlu melihat sisi lain dari koin: C ++.

Dalam OOP, kami memikirkan objek abstrak (dan merancang program yang sesuai), misalnya mobil yang dapat berhenti, berakselerasi, belok kiri atau kanan, dll. Sebuah struct dengan bundel fungsi sama sekali tidak sesuai dengan konsep.

Dengan objek "nyata" kita perlu menyembunyikan anggota misalnya, atau kita juga dapat memiliki warisan dengan "nyata" hubungan dan banyak lagi.

SETELAH MEMBACA KOMENTAR DI BAWAH INI: Ya benar bahwa (hampir) semuanya dapat dilakukan dengan C (itu selalu benar), tetapi pada pandangan pertama saya berpikir bahwa apa yang membedakan c dari c ++ adalah cara Anda berpikir ketika merancang sebuah program.

Satu-satunya hal yang benar-benar membuat perbedaan adalah penerapan kebijakan oleh kompiler . yaitu fungsi virtual murni, dan semacamnya. tetapi jawaban ini hanya akan berhubungan dengan masalah teknis, tapi saya pikir perbedaan utama (seperti yang disebutkan) adalah cara asli yang Anda pikirkan saat Anda kode, karena C ++ memberi Anda sintaks bawaan yang lebih baik untuk melakukan hal-hal seperti itu, daripada melakukan OOP di cara yang agak canggung di C.

Guy L
sumber
Tidak begitu yakin mengapa struct dengan "bundel fungsi" tidak sesuai dengan konsep? +1 untuk jawabannya
Dark Templar
1
Selain dari kontrol akses (pribadi / dilindungi / publik) segala sesuatu yang lain dapat dilakukan dengan struct.
Coder
1
@DarkTemplar: Ya, Anda dapat mencoba untuk meniru OOP dalam C (orang benar-benar telah menulis ebook tentang topik itu dan melakukannya di dunia nyata, walaupun sangat jarang), seperti Anda dapat mencoba meniru pemrograman fungsional di Jawa. Tetapi C tidak memberikan bantuan untuk itu, maka bahasa C tidak berorientasi objek .
1

Anda semacam mengatakannya sendiri. Sementara C memiliki benda-benda yang mirip objek, mereka masih bukan objek, dan itulah sebabnya C tidak dianggap sebagai bahasa OOP.

ryanzec
sumber
1
Yah, saya kira pertanyaannya adalah: mengapa dan di mana garis ditarik untuk apa objek dan apa yang tidak?
Dark Templar
1

Berorientasi Objek mengacu pada pola arsitektur (atau bahkan pola-meta), dan, bahasa yang memiliki fitur untuk membantu mengimplementasikan atau mengamanatkan penggunaan pola ini.

Anda dapat menerapkan desain "OO" (Gnome desktop mungkin adalah contoh terbaik dari OO yang dilakukan dalam C murni), saya bahkan telah melihat ini dilakukan dengan COBOL!

Namun mampu menerapkan dosis desain OO tidak membuat bahasa OO. Purist akan berpendapat bahwa Java dan C ++ tidak benar-benar OO karena Anda tidak dapat menimpa atau mewarisi "tipe" dasar seperti "int" dan "char", dan, Java tidak mendukung multiple inheritance. Tetapi karena mereka adalah bahasa OO yang paling banyak digunakan dan mendukung sebagian besar paradigma yang paling "nyata" programmer yang dibayar untuk menghasilkan kode kerja menganggap mereka sebagai bahasa OO.

C di sisi lain hanya mendukung struktur (seperti halnya COBOL, Pascal, dan puluhan bahasa prosedural lainnya), Anda dapat berargumen bahwa mendukung banyak pewarisan karena Anda dapat menggunakan fungsi apa pun pada bagian data apa pun, tetapi sebagian besar akan menganggap ini sebagai bug. dari fitur.

James Anderson
sumber
0

Mari kita lihat definisi OO:

  • Olahpesan
  • Enkapsulasi
  • Binding Terlambat

C tidak memberikan ketiganya. Secara khusus, itu tidak menyediakan Olahpesan , yang merupakan yang paling penting.

Jörg W Mittag
sumber
1
Saya pikir saya harus tidak setuju dengan itu. Anda pasti dapat memiliki perpesanan di C - bekerja dengan Objective C APIs dari C dan Anda menemukan bahwa secara mendalam - dan pengikatan yang terlambat dapat dilakukan melalui pointer fungsi, tetapi Anda tidak mendapatkan banyak gula sintaksis untuk menyembunyikannya. (Enkapsulasi sebenarnya mudah dalam C; petunjuk untuk tipe struktur yang tidak lengkap melakukan pekerjaan dengan sempurna.)
Donal Fellows
Warisan juga dianggap penting dalam OO, dan C tidak melakukan itu. Hal terdekat dengan enkapsulasi dalam C adalah file terpisah yang dapat memiliki staticfungsi internal ( ) dan anggota data.
David Thornley
@DonalFellows, pesan aktual yang lewat di Objective-C dapat dengan mudah diimplementasikan sebagai makro C99. Satu-satunya hal yang dilakukan oleh kompiler adalah ia menghasilkan semua struktur yang diperlukan secara statis dari beberapa baris kode tingkat tinggi. Sebagian besar jika tidak semua fitur tersedia dari C API.
qpr
0

Ada sejumlah bahan utama untuk OO, tetapi yang besar adalah bahwa sebagian besar kode tidak tahu apa yang ada di dalam objek (mereka melihat antarmuka permukaan, bukan implementasinya), bahwa keadaan suatu objek adalah unit yang dikelola (Yaitu, ketika objek berhenti menjadi, begitu juga keadaannya), dan ketika beberapa kode memanggil operasi pada objek, mereka melakukannya tanpa tahu persis apa operasi itu atau melibatkan (semua yang mereka lakukan adalah mengikuti pola untuk melempar "Pesan" di dinding).

C tidak enkapsulasi dengan baik; kode yang tidak melihat definisi struktur tidak dapat (secara sah) mengintip ke dalamnya. Yang perlu Anda lakukan adalah memasukkan definisi seperti ini di file header:

struct FooImpl;
typedef struct FooImpl *Foo;

Tentu saja, akan ada kebutuhan untuk fungsi yang membangun Foo(yaitu, pabrik) dan yang harus mendelegasikan beberapa pekerjaan ke objek yang dialokasikan itu sendiri (yaitu, melalui metode "konstruktor"), dan juga memiliki cara membuang objek lagi (sambil membiarkannya membersihkan melalui metode "destruktor") tapi itu detail.

Metode pengiriman (yaitu, pengiriman pesan) juga dapat dilakukan melalui konvensi bahwa elemen pertama dari struktur sebenarnya adalah pointer ke struktur yang penuh dengan pointer fungsi, dan bahwa masing-masing pointer fungsi tersebut harus menggunakan Fooargumen pertama. Pengiriman kemudian menjadi masalah mencari fungsi dan memanggilnya dengan penulisan ulang argumen yang tepat, yang tidak sulit dilakukan dengan makro dan sedikit kelicikan. (Tabel fungsi tersebut adalah inti dari apa sebenarnya kelas dalam bahasa seperti C ++.)

Selain itu, itu memberi Anda keterlambatan mengikat juga: semua kode pengiriman tahu adalah bahwa itu melibatkan offset tertentu ke dalam tabel yang ditunjuk oleh objek. Itu hanya perlu diatur selama alokasi dan inisialisasi objek. Dimungkinkan untuk menggunakan skema pengiriman yang lebih kompleks yang memberi Anda lebih banyak dinamika runtime (dengan biaya kecepatan) tetapi mereka ceri di atas mekanisme dasar.

Namun itu tidak berarti bahwa C adalah bahasa OO. Kuncinya adalah bahwa C membiarkan Anda melakukan sendiri semua pekerjaan rumit dengan menulis sendiri konvensi dan mekanisme pengiriman (atau menggunakan perpustakaan pihak ketiga). Itu banyak pekerjaan. Ini juga tidak memberikan dukungan sintaksis atau semantik, sehingga menerapkan sistem kelas penuh (dengan hal-hal seperti warisan) akan sangat menyakitkan; jika Anda berurusan dengan masalah kompleks yang digambarkan dengan baik oleh model OO, bahasa OO akan sangat berguna dalam menulis solusinya. Kompleksitas ekstra dapat dibenarkan.

Donal Fellows
sumber
0

Saya pikir C sangat baik dan layak untuk menerapkan konsep berorientasi objek, mengangkat bahu . Sebagian besar perbedaan seperti yang saya lihat di antara subset penyebut umum bahasa yang dianggap berorientasi objek bersifat kecil dan sintaksis dari sudut pandang pragmatis saya.

Mari kita mulai dengan, katakanlah, menyembunyikan informasi. Dalam C kita dapat mencapai itu hanya dengan menyembunyikan definisi struktur dan bekerja dengannya melalui pointer buram. Itu secara efektif memodelkan perbedaan publicvs privatebidang data seperti yang kita dapatkan dengan kelas. Dan itu cukup mudah dilakukan dan hampir tidak anti-idiomatik, karena pustaka C standar sangat bergantung pada ini untuk mencapai penyembunyian informasi.

Tentu saja Anda kehilangan kemampuan untuk dengan mudah mengontrol dengan tepat di mana struktur dialokasikan dalam memori dengan menggunakan jenis buram, tetapi itu hanya perbedaan yang patut diperhatikan antara, katakanlah, C dan C ++. C ++ jelas merupakan alat yang unggul ketika membandingkan kemampuannya untuk memprogram konsep-konsep berorientasi objek lebih dari C sambil tetap mempertahankan kontrol atas tata letak memori, tetapi itu tidak berarti bahwa Java atau C # lebih unggul daripada C dalam hal itu, karena keduanya membuat Anda benar-benar kehilangan kemampuan untuk mengontrol di mana objek dialokasikan dalam memori.

Dan kita harus menggunakan sintaksis seperti fopen(file, ...); fclose(file);sebagai lawan file.open(...); file.close();tetapi teriakan besar. Siapa yang peduli? Mungkin hanya seseorang yang sangat bersandar pada penyelesaian otomatis dalam IDE mereka. Saya akui itu bisa menjadi fitur yang sangat berguna dari sudut pandang praktis, tapi mungkin bukan yang mengharuskan diskusi tentang apakah suatu bahasa cocok untuk OOP.

Kami tidak memiliki kemampuan untuk mengimplementasikan protectedbidang secara efektif . Saya akan benar-benar tunduk di sana. Tetapi saya tidak berpikir ada aturan konkret yang mengatakan, " Semua bahasa OO harus memiliki fitur untuk memungkinkan subclass mengakses anggota kelas dasar yang masih belum dapat diakses oleh klien normal ." Selain itu saya jarang melihat kasus penggunaan untuk anggota yang dilindungi yang setidaknya tidak sedikit curiga menjadi rintangan pemeliharaan.

Dan tentu saja kita harus "meniru" polimorfisme OO dengan tabel fungsi pointer dan pointer ke mereka untuk pengiriman dinamis dengan sedikit lebih boilerplate untuk menginisialisasi analog vtablesdan vptrs, tetapi sedikit boilerplate tidak pernah menyebabkan saya banyak kesedihan.

Warisan adalah cara yang sama. Kita dapat dengan mudah memodelkan itu melalui komposisi, dan pada cara kerja internal kompiler itu bermuara pada hal yang sama. Tentu saja kita kehilangan keamanan tipe jika kita ingin downcast , dan di sana saya katakan jika Anda ingin downcasting sama sekali, untuk tolong jangan menggunakan C untuk itu karena hal-hal yang dilakukan orang di C untuk meniru downcasting dapat mengerikan dari suatu tipe sudut pandang keamanan, tapi saya lebih suka orang tidak downcast sama sekali. Jenis keamanan adalah sesuatu yang Anda dapat dengan mudah mulai ketinggalan dalam C karena kompiler menyediakan begitu banyak kelonggaran untuk menafsirkan hal-hal hanya sebagai bit dan byte, mengorbankan kemampuan untuk menangkap calon kesalahan pada waktu kompilasi, tetapi beberapa bahasa dianggap berorientasi objek bukan bahkan diketik secara statis.

Tidak tahu, saya pikir tidak apa-apa. Tentu saja saya tidak akan menggunakan C untuk mencoba membuat basis kode skala besar yang sesuai dengan prinsip-prinsip SOLID, tapi itu belum tentu karena kedatangannya yang pendek di bidang berorientasi objek. Banyak fitur yang akan saya lewatkan jika saya mencoba menggunakan C untuk tujuan seperti itu akan terkait dengan fitur bahasa yang tidak secara langsung dianggap sebagai prasyarat untuk OOP seperti keselamatan tipe kuat, destruktor yang secara otomatis dipanggil ketika benda keluar dari ruang lingkup, operator kelebihan muatan, templat / generik, dan penanganan pengecualian. Saat itulah saya kehilangan fitur tambahan yang saya raih untuk C ++.


sumber
1
Saya tidak yakin bagaimana konstruktor tidak dapat dianggap sebagai prasyarat untuk OOP. Bagian dari esensi dasar enkapsulasi adalah kemampuan untuk memastikan invarian untuk suatu objek. Dan itu membutuhkan kemampuan untuk menginisialisasi objek dengan benar di dalam invarian tersebut. Itu membutuhkan konstruktor: satu fungsi atau lebih, sehingga Anda tidak bisa mengatakan bahwa objek itu ada sampai setidaknya salah satu dari mereka dipanggil.
Nicol Bolas
Ketika kita memiliki informasi yang bersembunyi dengan tipe buram maka satu-satunya cara untuk membuat instance dan menyalin / mengkloning dan menghancurkannya adalah melalui fungsi analogis yang berfungsi sebagai konstruktor dan destruktor dengan kemampuan yang sama banyaknya untuk mempertahankan invarian tersebut. Hanya saja tidak secara langsung dimodelkan ke dalam bahasa dan mungkin menyerupai bentuk foo_createdan foo_destroydan foo_clone, misalnya
Yang kita perlukan untuk mempertahankan invarian struct Foodalam kasus seperti ini adalah untuk memastikan anggota datanya tidak dapat diakses dan dimutasi oleh dunia luar, yang diberikan oleh tipe-tipe buram (dideklarasikan tetapi tidak didefinisikan ke dunia luar) segera. Ini bisa dibilang bentuk yang lebih kuat dari penyembunyian informasi, setara dengan yang ada pimpldi C ++.
Ya, saya tahu bagaimana orang menerapkan OOP di C, terima kasih. Maksud saya adalah bahwa pernyataan Anda bahwa konstruktor "tidak secara langsung dianggap sebagai prasyarat untuk OOP" salah.
Nicol Bolas
Saya mengerti, biar saya perbaiki ... tetapi dalam hal ini dapatkah kita mengatakan bahwa C memang menyediakan (cukup?) Dukungan untuk destruktor dan konstruktor?
-1

Bukan pertanyaan yang buruk.

Jika Anda akan memanggil c bahasa OO Anda perlu memanggil semua bahasa prosedural OO juga. Jadi itu akan membuat istilah itu tidak berarti. c tidak memiliki dukungan bahasa untuk OO. Jika memiliki struct, tetapi struct tidak typesada kelas.

Sebenarnya c tidak memiliki banyak fitur sama sekali dibandingkan dengan kebanyakan bahasa. Ini sebagian besar digunakan untuk kecepatan, kesederhanaan, popularitas dan dukungan termasuk banyak perpustakaan.

Glen P
sumber