Ketika struktur data (misalnya, antrian) diimplementasikan menggunakan bahasa OOP, beberapa anggota struktur data harus bersifat pribadi (misalnya, jumlah item dalam antrian).
Antrian juga dapat diimplementasikan dalam bahasa prosedural menggunakan a struct
dan satu set fungsi yang beroperasi pada struct
. Namun, dalam bahasa prosedural Anda tidak dapat menjadikan anggota sebagai struct
pribadi. Apakah anggota struktur data diimplementasikan dalam bahasa prosedural dibiarkan publik, atau adakah trik untuk menjadikannya pribadi?
object-oriented
data-structures
history
Christopher
sumber
sumber
Jawaban:
OOP tidak menemukan enkapsulasi dan tidak identik dengan enkapsulasi. Banyak bahasa OOP tidak memiliki pengubah akses gaya C ++ / Java. Banyak bahasa non-OOP memiliki berbagai teknik yang tersedia untuk menawarkan enkapsulasi.
Salah satu pendekatan klasik untuk enkapsulasi adalah penutupan , seperti yang digunakan dalam pemrograman fungsional . Ini secara signifikan lebih tua dari OOP tetapi setara. Misalnya dalam JavaScript kita mungkin membuat objek seperti ini:
plus2
Objek di atas tidak memiliki anggota yang akan memungkinkan akses langsung kex
- itu sepenuhnya dirangkum. Theadd()
metode adalah penutupan atasx
variabel.Bahasa C mendukung beberapa jenis enkapsulasi melalui mekanisme file tajuknya , khususnya teknik pointer buram . Dalam C, dimungkinkan untuk mendeklarasikan nama struct tanpa mendefinisikan anggotanya. Pada titik itu tidak ada variabel dari jenis struct yang dapat digunakan, tetapi kita dapat menggunakan pointer ke struct itu secara bebas (karena ukuran pointer struct diketahui pada waktu kompilasi). Misalnya, pertimbangkan file tajuk ini:
Kami sekarang dapat menulis kode yang menggunakan antarmuka Adder ini, tanpa memiliki akses ke bidangnya, misalnya:
Dan inilah detail implementasi yang dirangkum secara total:
Ada juga kelas bahasa pemrograman modular , yang berfokus pada antarmuka tingkat modul. Keluarga bahasa ML termasuk OCaml mencakup pendekatan yang menarik untuk modul yang disebut functors . OOP dibayangi dan sebagian besar dimasukkan pemrograman modular, namun banyak keuntungan yang diklaim OOP lebih tentang modularitas daripada orientasi objek.
Ada juga pengamatan bahwa kelas-kelas dalam bahasa OOP seperti C ++ atau Java sering tidak digunakan untuk objek (dalam arti entitas yang menyelesaikan operasi melalui pengikatan / pengiriman dinamis) tetapi hanya untuk tipe data abstrak (di mana kami mendefinisikan antarmuka publik yang menyembunyikan rincian implementasi internal). Makalah Tentang Memahami Abstraksi Data, Revisited (Cook, 2009) membahas perbedaan ini secara lebih rinci.
Tapi ya, banyak bahasa tidak memiliki mekanisme enkapsulasi sama sekali. Dalam bahasa ini, anggota struktur dibiarkan publik. Paling-paling, akan ada konvensi penamaan yang melarang penggunaan. Misalnya saya pikir Pascal tidak memiliki mekanisme enkapsulasi yang berguna.
sumber
Adder self = malloc(sizeof(Adder));
? Ada alasan untuk mengetik pointer dansizeof(TYPE)
umumnya disukai.sizeof(*Adder)
, karena*Adder
bukan tipe, sama seperti*int *
bukan tipe. UngkapannyaT t = malloc(sizeof *t)
idiomatis dan benar. Lihat hasil edit saya.private static
variabel di Jawa. Demikian juga untuk C, Anda dapat menggunakan pointer buram untuk meneruskan data dalam Pascal tanpa menyatakan apa itu. Classic MacOS menggunakan banyak pointer buram karena bagian publik dan pribadi dari suatu catatan (struktur data) dapat disatukan. Saya ingat Window Manager melakukan banyak hal ini karena bagian dari Window Record bersifat publik tetapi beberapa informasi internal juga disertakan._private_member
danoutput_property_
, atau teknik yang lebih canggih untuk membuat objek yang dapat di-imutable.Pertama, menjadi prosedural versus berorientasi objek tidak ada hubungannya dengan publik vs swasta. Banyak bahasa berorientasi objek tidak memiliki gagasan tentang kontrol akses.
Kedua, dalam "C" - yang oleh kebanyakan orang disebut prosedural, dan tidak berorientasi objek, ada banyak trik yang dapat Anda gunakan untuk secara efektif membuat hal-hal pribadi. Yang sangat umum adalah menggunakan pointer buram (mis. Void *). Atau - Anda dapat meneruskan mendeklarasikan objek, dan tidak mendefinisikannya dalam file header.
foo.h:
foo.c:
Lihatlah SDK windows! Ini menggunakan HANDLE dan UINT_PTR, dan hal-hal seperti itu menjadi pegangan umum untuk memori yang digunakan dalam API - secara efektif membuat implementasi pribadi.
sumber
"Tipe data buram" adalah konsep yang terkenal ketika saya melakukan gelar ilmu komputer saya 30 tahun yang lalu. Kami tidak membahas OOP karena tidak digunakan secara umum pada saat itu dan "pemrograman fungsional" dianggap lebih benar.
Modula-2 memiliki dukungan langsung untuk mereka, lihat https://www.modula2.org/reference/modules.php .
Telah dijelaskan oleh Lewis Pringle bagaimana maju menyatakan sebuah struct dapat digunakan dalam C. Tidak seperti Modul-2, fungsi pabrik harus disediakan untuk membuat objek. ( Metode virtual juga mudah diimplementasikan dalam C dengan memiliki anggota pertama dari sebuah struct menjadi pointer ke struct lain yang berisi fungsi pointer ke metode.)
Seringkali konvensi juga digunakan. Misalnya, bidang apa pun yang dimulai dengan "_" tidak boleh diakses di luar file yang memiliki data. Ini mudah ditegakkan dengan penciptaan alat pengecekan khusus.
Setiap proyek skala besar yang saya kerjakan, (sebelum saya pindah ke C ++ lalu C #) memiliki sistem untuk mencegah "pribadi" data diakses oleh kode yang salah. Itu hanya sedikit kurang standar daripada sekarang.
sumber
Perhatikan ada banyak bahasa OO tanpa kemampuan bawaan untuk menandai anggota sebagai pribadi. Ini dapat dilakukan dengan konvensi, tanpa perlu kompiler untuk menegakkan privasi. Misalnya, orang akan sering mengawali variabel pribadi dengan garis bawah.
Ada beberapa teknik untuk mempersulit mengakses variabel "pribadi", yang paling umum adalah idiom PIMPL . Ini menempatkan variabel pribadi Anda dalam struct terpisah, dengan hanya pointer yang dialokasikan dalam file header publik Anda. Ini berarti dereferensi tambahan dan pemain untuk mendapatkan variabel pribadi, seperti
((private_impl)(obj->private))->actual_value
, yang mengganggu, sehingga dalam praktiknya jarang digunakan.sumber
Struktur data tidak memiliki "anggota", hanya bidang data (dengan asumsi itu adalah tipe rekaman). Visibilitas biasanya ditetapkan untuk seluruh tipe. Namun, itu mungkin tidak membatasi seperti yang Anda pikirkan, karena fungsinya bukan bagian dari catatan.
Mari kita mundur dan mendapatkan sedikit sejarah di sini ...
Paradigma pemrograman yang dominan sebelum OOP disebut pemrograman terstruktur . Tujuan utama awal dari ini adalah untuk menghindari penggunaan pernyataan lompatan yang tidak terstruktur ("goto" s). Ini adalah paradigma berorientasi aliran kontrol (sementara OOP lebih berorientasi pada data), tetapi masih merupakan perpanjangan alami untuk berusaha menjaga data terstruktur secara logis seperti kode.
Unggulan lain dari pemrograman terstruktur adalah penyembunyian informasi , gagasan bahwa implementasi struktur kode (yang cenderung sering berubah) harus dipisahkan dari antarmuka (yang idealnya tidak akan berubah hampir sebanyak). Ini dogma sekarang, tetapi di masa lalu, banyak orang benar-benar menganggap lebih baik bagi setiap pengembang untuk mengetahui detail dari keseluruhan sistem, jadi ini adalah ide kontroversial. Edisi asli Brook's The Mythical Man Month sebenarnya membantah informasi yang disembunyikan.
Bahasa pemrograman kemudian dirancang secara eksplisit untuk menjadi bahasa Pemrograman Terstruktur yang baik (misalnya, Modula-2 dan Ada) umumnya memasukkan informasi yang bersembunyi sebagai konsep dasar, dibangun di sekitar semacam konsep fasilitas kohesif fungsi (dan semua jenis, konstanta, dan objek yang mungkin diperlukan). Dalam Modula-2 ini disebut "Modul", di Ada "Paket". Banyak bahasa OOP modern menyebut konsep yang sama "ruang nama". Ruang nama ini adalah fondasi organisasi pengembangan dalam bahasa-bahasa ini, dan untuk sebagian besar tujuan dapat digunakan serupa dengan kelas OOP (tentu saja, tanpa dukungan nyata untuk warisan).
Jadi di Modula-2 dan Ada (83) Anda bisa mendeklarasikan rutin, tipe, konstanta, atau objek apa pun dalam namespace privat atau publik, tetapi jika Anda memiliki tipe record, tidak ada (mudah) cara untuk mendeklarasikan beberapa record field publik dan lainnya pribadi. Seluruh catatan Anda bersifat publik, atau tidak.
sumber
object.method()
doa hanya sintaksis gula. IMHO Penting - lihat Prinsip Akses / Referensi Seragam Meyer - tetapi masih berupa gula sintaksis.object.method()
sebagai bentuk alternatifmethod(object, ...)
untuk orang-orang yang tidak bisa membuat lompatan konseptual.Di C Anda sudah bisa membagikan pointer ke tipe yang dideklarasikan tetapi tidak terdefinisi seperti yang dikatakan orang lain, yang pada dasarnya membatasi akses ke semua bidang.
Anda juga dapat memiliki fungsi pribadi dan publik berdasarkan modul-ke-modul. Fungsi yang dinyatakan statis di file sumber tidak terlihat di luar, bahkan jika Anda mencoba menebak namanya. Demikian pula, Anda dapat memiliki variabel global tingkat file statis, yang umumnya merupakan praktik buruk tetapi memungkinkan isolasi berdasarkan modul.
Mungkin penting untuk menekankan bahwa pembatasan akses sebagai konvensi terstandarisasi dengan baik daripada konstruksi yang didukung bahasa berfungsi dengan baik (lihat Python). Selain itu, membatasi akses ke bidang objek hanya akan melindungi pemrogram ketika ada kebutuhan untuk mengubah nilai data di dalam objek setelah pembuatan. Yang sudah menjadi bau kode. Bisa dibilang, C dan khususnya
const
kata kunci C ++ untuk metode dan argumen fungsi adalah bantuan yang jauh lebih besar bagi programmer daripada Java yang agak miskinfinal
.sumber
static
data global dan operasi (yang berarti mereka tidak disajikan kepada linker untuk digunakan dari kompilasi lain). Anda dapat berargumen bahwa dukungan apa pun yang dimiliki C untuk praktik desain perangkat lunak yang baik selain dari itu adalah peretasan, dan bukan bagian dari desain asli bahasa tersebut pada tahun 1972.Jika definisi Anda tentang Publik adalah kemampuan untuk mengakses implementasi dan data / properti melalui kode Anda sendiri di setiap titik, jawabannya adalah sederhana: Ya . Namun, itu disarikan dengan beragam cara - tergantung pada bahasanya.
Saya harap ini menjawab pertanyaan Anda dengan ringkas.
sumber
Berikut ini adalah contoh-contoh yang sangat sederhana: di Java,
interface
s mendefinisikan objek, tetapiclass
es tidak. Aclass
mendefinisikan Tipe Data Abstrak, bukan objek.Ergo, setiap kali Anda menggunakan
private
dalamclass
Java, Anda memiliki contoh struktur data dengan anggota pribadi yang tidak berorientasi objek.sumber