Perbedaan antara pesan dan metode?

13

Di Objective C Anda memiliki konsep mengirim pesan ke objek lain, dan, well ini sangat mirip dengan metode pemanggilan dalam bahasa seperti C # dan Java.

Tetapi apa sebenarnya perbedaan yang halus itu? Bagaimana saya harus memikirkan pengiriman pesan ketika memikirkan kode saya?

Catatan: Hanya sedikit latar belakang di sini, saya adalah pengembang C # / Java yang mencoba memahami beberapa konsep tentang Objective C.

Vidar
sumber
2
Karena mereka semua bahasa yang berbeda, perbedaannya tidak halus. Mereka bahasa yang berbeda. "Ketika memikirkan kode saya"? Kode apa? Saat memikirkan Java atau C #, Anda tidak memikirkan pesan. Anda memikirkan metode. Bisakah Anda mengklarifikasi bagaimana bahasa yang tidak terkait dengan konsep yang tidak terkait dapat memiliki perbedaan "halus"?
S.Lott
1
Silakan ajukan pertanyaan Anda di stackoverflow.com
Amir Rezaei
1
Haruskah pertanyaan ini benar-benar ada di StackOverflow? Ini pertanyaan tentang konsep pemrograman bukan masalah tentang beberapa kode yang saya punya. Mungkin saya salah, saya tidak tahu - batasnya kabur ...
Vidar
1
@Vidar, pertanyaannya tidak subyektif. Anda sedang mencari definisi buku teks. Programmer lebih menyukai pendapat, pengalaman, dan pertanyaan subyektif.
Stephen Furlani
1
OK - apakah ada cara agar moderator memindahkan pertanyaan ini ke StackOverflow?
Vidar

Jawaban:

10

Pesan adalah nama pemilih, dan parameter untuk pemilih itu.

Selektor adalah simbol.

Metode adalah sepotong kode dalam kelas yang diidentifikasi oleh pemilih.

Dengan kata lain, [foo bar: baz]katakan "kirim pesan yang disebut @selector(bar:)dengan parameter bazke objek foo. Anda bisa mengirim pesan itu ke banyak objek berbeda.

Sebaliknya, metode bar: untuk Foomungkin terlihat seperti

-(int)bar:(int)n {
  return n + 1;
}

tapi untuk yang FooTwomungkin terlihat seperti

-(int)bar:(int)n {
  return n + 2;
}

(Saya harap saya memiliki hak sintaksis; sudah lama sejak saya terakhir menyentuh Objective-C.)

Ketika Anda mengirim pesan, kernel Objective-C mengirimkan pesan fooyang memutuskan apakah ia memahami pesan tersebut. Ia memutuskan ini berdasarkan apakah ia dapat menemukan metode yang diidentifikasi oleh pemilih itu.

Dua metode dengan nama yang sama, dan satu pesan.

Mungkin juga untuk objek hanya meneruskan pesan tertentu (atau serangkaian pesan) ke objek lain untuk diproses. Dalam hal ini, Anda mengirim pesan ke objek proxy ini, yang tidak memiliki metode untuk mencocokkan pesan itu , dan proxy meneruskan pesan ke objek yang dibungkus.

Frank Shearar
sumber
jadi ... pesannya adalah ketika Anda memanggil dispinterface (pemilih a.invoke, args) dan sebuah metode adalah saat Anda memanggil antarmuka (a.methodName)? Bukankah itu membuat java, JavaScript, semua bahasa dinamis memiliki pesan karena semuanya terjadi melalui antarmuka ganda dan bukan lompatan langsung dan diimbangi menjadi lompatan vtable)?
Dmitry
3

Dari sudut pandang teori semata, tidak ada perbedaan di antara keduanya - ada sejumlah bukti formal yang menunjukkan bahwa keduanya sama-sama setara, dan keduanya dapat diimplementasikan sepenuhnya dalam hal yang lain.

Dari sudut pandang yang sedikit kurang teoretis, ada satu perbedaan yang mungkin: dalam implementasi tipikal, tabel fungsi virtual dialokasikan secara statis dan konten setiap vtable diperbaiki pada waktu kompilasi. Sebaliknya, pencarian pesan biasanya dilakukan dengan semacam objek peta, yang biasanya dinamis, artinya Anda dapat memodifikasinya saat runtime. Ini membuatnya relatif mudah untuk menambahkan respons baru ke pesan di kelas yang ada. Sayangnya, dalam kebanyakan kasus ini sebagian besar tetap teoretis. Pertama, pada dasarnya Anda berurusan dengan kode diri memodifikasi, yang kebanyakan orang memutuskan adalah ide yang cukup buruk panjangwaktu lalu. Kedua, untuk membuatnya sangat bermakna, Anda perlu mengkompilasi kode baru ke dalam kelas yang ada untuk menanggapi pesan baru yang Anda dukung. Tanpa itu, yang Anda dapatkan hanyalah kemampuan untuk menambahkan nama baru secara dinamis untuk metode yang ada.

Seperti yang tersirat pada akhir paragraf sebelumnya, dari sudut pandang yang benar-benar praktis, hanya ada sedikit perbedaan di antara keduanya. Mereka hanyalah dua (sangat sedikit) cara berbeda untuk mendukung ikatan yang terlambat. Meskipun pencarian berbasis pesan umumnya sedikit lebih lambat, itu akan sangat tidak biasa untuk perbedaannya menjadi benar-benar signifikan. Untuk tujuan paling praktis, mereka hanya dua cara berbeda untuk mencapai hal yang sama.

Jerry Coffin
sumber
2
Apakah Anda memiliki referensi yang menunjukkan buktinya? Saya ingin melihatnya. Ada perbedaan besar antara doa metode Java dan pengiriman pesan Smalltalk, bukan hanya karena ikatan yang terlambat, tetapi juga karena decoupling pengirim dan penerima: Anda tidak dapat mengetahui apakah penerima pesan memprosesnya, atau meneruskan pesan tersebut aktif, misalnya.
Frank Shearar
1

Di Objective-C, pesan terikat terlambat. Itu mereka diselesaikan pada saat runtime. C # mendukung konstruk serupa melalui kata kunci Dinamis yang menyatakan objek sebagai ikatan akhir juga.

Michael Brown
sumber
0

Biasanya pemanggilan metode diselesaikan pada waktu kompilasi (kecuali jika Anda menggunakan refleksi di Java), sementara pesan di Objective C dikirim pada waktu berjalan.

Heiko Rupp
sumber
2
Jika pemanggilan metode diselesaikan adalah waktu kompilasi, Anda tidak menggunakan OOP, Anda menggunakan gula sintaksis untuk fungsi yang kelebihan beban dengan mengambil structsebagai parameter pertama. Terlambat bindung adalah bagian penting dari polimorfisme dan karenanya OOP.
2
Iya. Tapi tetap saja Anda hanya bisa mengkode panggilan metode terhadap sesuatu (di Jawa) yang dikenal pada saat kompilasi. Memanggil MyObject.foo () akan memberikan kesalahan jika MyObject atau MyInterface tidak memiliki metode foo () yang ditentukan. ObjC akan memungkinkan Anda mengirimkan pesan 'foo' ke objek MyObject - dan jika MyObject tidak memiliki 'foo', ini akan meledak pada saat dijalankan.
Heiko Rupp
Saya pikir Objective C adalah bahasa yang dikompilasi?
Vidar
1
Itu tidak nyata untuk pengikatan awal / akhir (pengetikan dinamis vs pengetikan struktural - dalam contoh Anda, pemanggilan metode diperiksa pada saat bersamaan tetapi tidak harus dikirim ). @Vidar: Ya, tapi ini menambah keajaiban untuk fitur dinamis. Anda juga dapat mengkompilasi Python.
@Vidar: Ini bukan masalah yang dikompilasi vs ditafsirkan, melainkan statis vs dinamis. Dalam bahasa OOP statis seperti Java, kompiler memeriksa untuk memastikan bahwa kelas mendefinisikan metode selama fase kompilasi. Dalam bahasa yang diketik secara dinamis seperti Objective-C, pesan dilewatkan saat runtime.
mipadi
-1

Pesan ditangani oleh kernel atau oleh bahasa itu sendiri (untuk ObjC misalnya, ada kode perakitan sangat kecil yang melakukannya).

Dalam kernel linux misalnya, pesan dilakukan dengan panggilan sistem / fungsi: Anda dapat menemukannya jika Anda mencari tentang pemrograman sistem unix.

Perbedaan utama antara pemanggilan metode dan pesan adalah ini:

  • pemanggilan metode hanya terjadi di kode Anda: di ASM itu diterjemahkan oleh PUSH dari argumen yang diteruskan.

  • pesan kernel sebagian besar adalah sesuatu yang dikirim ke kernel yang dilacak dan dikirim kembali ke proses tertentu. Saya mungkin mengira mereka untuk pipa, tetapi apa pun: tahu sudah ada mekanisme yang memungkinkan Anda untuk menjalankan beberapa program pada saat yang sama dan membiarkan berkomunikasi pada saat yang sama. Tentu saja, jangan berharap ini akan bekerja dengan cara yang sama pada windows atau OS lainnya.

jokoon
sumber
Ini bukan "pesan yang lewat" karena ini berlaku untuk bahasa pemrograman.
mipadi