Apa yang mengikat awal dan terlambat?


77

Saya terus mendengar tentang mengikat awal dan terlambat, tetapi saya tidak mengerti apa itu. Saya menemukan penjelasan berikut yang tidak saya mengerti:

Pengikatan awal mengacu pada penugasan nilai ke variabel selama waktu desain sedangkan pengikatan akhir mengacu pada penugasan nilai ke variabel selama waktu berjalan.

Bisakah seseorang mendefinisikan dua jenis ikatan dan membandingkannya?


1
waktu kompilasi vs runtime.
barlop

Berikut ini adalah bacaan yang bagus tentang hal ini: en.wikibooks.org/wiki/Introduction_to_Programming_Languages/…
Jay Elston

Jawaban:


84

Ada dua konsep utama dalam kebingungan: mengikat dan memuat. Itu digabungkan dengan konsep DataBinding, yang merupakan suatu tempat di tengah sering melakukan keduanya. Setelah mempertimbangkannya, saya akan menambahkan satu konsep lagi, untuk melengkapi trifecta, pengiriman.

Jenis

Late Binding : type tidak diketahui sampai variabel dijalankan saat run-time; biasanya melalui penugasan tetapi ada cara lain untuk memaksa suatu jenis; bahasa yang diketik secara dinamis menyebut ini fitur yang mendasarinya, tetapi banyak bahasa yang diketik secara statis memiliki beberapa metode untuk mencapai pengikatan akhir

Diterapkan sering menggunakan tipe dinamis [khusus], introspeksi / refleksi, opsi flag dan kompiler, atau melalui metode virtual dengan meminjam dan memperluas pengiriman dinamis

Binding Awal : tipe diketahui sebelum variabel dijalankan selama run-time, biasanya melalui cara statik, deklaratif

Diimplementasikan sering menggunakan tipe primitif standar

Fungsi

Pengiriman Statis : diketahui, fungsi spesifik atau subrutin pada waktu kompilasi; itu tidak ambigu dan cocok dengan tanda tangan

Diimplementasikan sebagai fungsi statis; tidak ada metode yang dapat memiliki tanda tangan yang sama

Pengiriman dinamis : bukan fungsi atau subrutin tertentu pada waktu kompilasi; ditentukan oleh konteks selama eksekusi. Ada dua pendekatan berbeda untuk "pengiriman dinamis," dibedakan dengan informasi kontekstual apa yang digunakan untuk memilih implementasi fungsi yang sesuai.

Dalam pengiriman tunggal [ dinamis ] , hanya jenis instance yang digunakan untuk menentukan implementasi fungsi yang sesuai. Dalam bahasa yang diketik secara statis, apa artinya ini dalam praktek adalah bahwa tipe instance memutuskan implementasi metode mana yang digunakan terlepas dari tipe referensi yang ditunjukkan ketika variabel dideklarasikan / ditugaskan. Karena hanya satu tipe - tipe instance objek - yang digunakan untuk menyimpulkan implementasi yang tepat, pendekatan ini disebut "pengiriman tunggal".

Ada juga beberapa pengiriman [ dinamis ] , di mana tipe parameter input juga membantu menentukan implementasi fungsi mana yang akan dipanggil. Karena beberapa tipe - baik tipe instance dan tipe parameter - mempengaruhi penerapan metode mana yang dipilih, pendekatan ini dijuluki "pengiriman ganda".

Diimplementasikan sebagai fungsi virtual atau abstrak; petunjuk lain termasuk metode yang diganti, disembunyikan, atau dibayangi.

NB: Apakah metode overloading melibatkan pengiriman dinamis atau tidak, tergantung pada bahasa. Misalnya, di Jawa, metode kelebihan beban dikirim secara statis.

Nilai-nilai

Pemuatan Malas : strategi inisialisasi objek yang menentang penetapan nilai sampai dibutuhkan ; memungkinkan objek berada pada kondisi yang pada dasarnya valid tetapi tidak lengkap dan menunggu sampai data diperlukan sebelum memuatnya; sering ditemukan sangat berguna untuk memuat dataset besar atau menunggu sumber daya eksternal

Diimplementasikan sering dengan sengaja tidak memuat koleksi atau daftar ke objek komposit selama panggilan konstruktor atau inisialisasi sampai beberapa penelepon hilir meminta untuk melihat konten koleksi itu (mis. Get_value_at, get_all_as, dll). Variasi termasuk memuat informasi meta tentang koleksi (seperti ukuran atau kunci), tetapi menghilangkan data aktual; juga menyediakan mekanisme untuk beberapa runtime untuk menyediakan pengembang dengan skema implementasi tunggal yang cukup aman dan efisien

Eager Loading : strategi inisialisasi objek yang segera melakukan semua penetapan nilai agar semua data yang diperlukan harus lengkap sebelum menganggap dirinya dalam keadaan valid.

Diimplementasikan sering dengan menyediakan objek komposit dengan semua data yang diketahui sesegera mungkin, seperti saat panggilan konstruktor atau inisialisasi

Pengikatan Data : sering melibatkan pembuatan tautan atau peta aktif antara dua aliran informasi yang kompatibel sehingga perubahan terhadap satu tercermin kembali ke yang lain dan sebaliknya; Agar kompatibel, mereka seringkali harus memiliki tipe dasar, atau antarmuka yang sama

Sering diimplementasikan sebagai upaya untuk menyediakan sinkronisasi yang lebih bersih dan konsisten antara berbagai aspek aplikasi (misalnya model tampilan untuk melihat, model ke pengontrol, dll.) Dan berbicara tentang konsep seperti sumber dan target, titik akhir, ikatan / tidak mengikat, pembaruan, dan acara seperti on_bind, on_property_change, on_explicit, on_out_of_scope


EDIT NOTE: Edit besar terakhir untuk memberikan deskripsi contoh bagaimana ini sering terjadi. Contoh kode tertentu sepenuhnya bergantung pada implementasi / runtime / platform


2
Jawaban ini tampaknya terlalu spesifik untuk bahasa berorientasi objek.
Jack

27

Apa pun yang diputuskan oleh kompiler saat mengkompilasi dapat merujuk ke AWAL / BULU WAKTU Binding dan apa pun yang akan diputuskan di RUNTIME disebut LATE / RUNTIME mengikat.

Sebagai contoh,

Metode Overloading dan Metode Overriding .

1) Dalam Metode Overloading panggilan metode Anda ke metode diputuskan oleh kompiler dalam arti bahwa fungsi yang akan dipanggil ditentukan oleh kompiler Anda pada waktu kompilasi. Oleh karena itu menjadi BINDING AWAL .

2) Dalam metode Overriding, diputuskan pada RUNTIME metode mana yang akan dipanggil. Jadi itu disebut sebagai BINDING TERLAMBAT .

Mencoba membuatnya sederhana dan mudah didapat. Semoga ini membantu.


9

Mengikat terlambat adalah ketika perilaku dievaluasi saat runtime. Ini penting ketika Anda memang ingin menentukan cara bertindak berdasarkan informasi yang Anda miliki saat program berjalan. Contoh paling jelas menurut saya adalah mekanisme fungsi virtual, khususnya di C ++.

class A
{
public:
    void f() {}
    virtual void g() {}
};

class B : public A
{
    void f() {}
    virtual void g() {}
};

int main()
{
    A* a = new B;
    a->f();
    a->g();
}

Dalam contoh ini, a->f()sebenarnya akan memanggil void A::f(), karena itu terikat awal (atau statis), dan program saat runtime berpikir itu hanya sebuah pointer ke Avariabel tipe, sedangkan a->g()sebenarnya akan memanggil void B::g(), karena kompiler, melihat g()adalah virtual, menyuntikkan kode untuk melihat alamat dari fungsi yang benar untuk memanggil saat runtime.


1
"Runtime"? Anda sedang berbicara tentang C ++. C ++ mengkompilasi langsung ke kode mesin, tidak perlu runtime untuk menyelesaikan metode virtual.
tdammers

3
@tdammers C ++ sebenarnya membutuhkan run time library, meskipun tidak untuk panggilan virtual. Jika Anda membaca dengan cermat, Anda akan melihat bahwa jawaban ini mengatakan kompiler "menyuntikkan kode untuk mencari alamat fungsi yang benar [...] saat runtime".

Yah, tetapi "kode untuk mencari alamat fungsi yang benar" pada dasarnya hanya tipe-agnostik penunjuk dua-tahap dereference diikuti oleh pemanggilan fungsi. Tidak ada "pemikiran" yang terlibat; satu-satunya alasan ia bekerja dengan andal adalah karena kompiler melakukan pengecekan tipe pada waktu kompilasi ; pada saat run-time, kode yang dihasilkan mempercayai kompiler untuk melakukan pekerjaan rumah pemeriksaan tipe. Jika Anda menggunakan gips yang tidak aman (misalnya gips penunjuk gaya-C), Anda dapat secara legal memperlakukan objek C ++ sebagai objek dari kelas yang salah, tetapi vtabelnya akan benar-benar kacau dan kodenya rusak begitu saja.
tdammers

@tdammers Saya mencoba untuk menjauh dari jawaban semacam itu, karena ini adalah detail implementasi dari kompiler, yang mungkin, atau mungkin tidak benar untuk beberapa kompiler esoterik. Yang penting adalah konsepnya.
Yam Marcovic

1
@tdammers Dan dengan "runtime" Maksudku "program saat runtime". Jelas C ++ tidak dikelola. Tetapi karena Anda menunjukkan kepada saya itu dapat menyebabkan kebingungan, saya mengubahnya menjadi kata-kata penuh.
Yam Marcovic

5

jika Anda terbiasa dengan fungsi pointer ini akan menjadi contoh. Fungsi yang didefinisikan dapat dikatakan mengikat awal. sedangkan jika Anda menggunakan Function pointer, Binding yang terlambat.

  int add(int x,int y)
  {
    return x+y;
  }
  int sub(int x,int y)
  {
      return x-y;
  }


    int main()
    {
     //get user choice
     int(*fp)(int,int);
     //if add
      fp=add;
     //else if sub
     fp=sub;
     cout<<fp(2,2);
    }

di sini fungsi menambah dan sub fungsi (alamatnya diikat pada kompilasi waktu-linker)

tetapi pointer fungsi terlambat mengikat fp dapat memanggil add atau sub tergantung pada pilihan pengguna [saat runtime].


3

Ikatan awal dan akhir hanya masuk akal dalam konteks jenis dan bukan cara Anda menggambarkannya. Hampir semua bahasa modern diketik dalam arti bahwa semua nilai memiliki tipe tetap. Perbedaannya muncul ketika kita melihat bahasa yang diketik secara dinamis vs. statis. Dalam bahasa yang diketik secara dinamis, variabel tidak memiliki tipe sehingga mereka dapat merujuk ke nilai dari jenis apa pun dan ini berarti bahwa ketika Anda memanggil metode pada objek yang dirujuk oleh beberapa variabel, satu-satunya cara untuk menentukan apakah panggilan itu valid atau tidak adalah dengan mencari kelas untuk objek dan melihat apakah metode itu benar-benar ada. Hal ini memungkinkan untuk beberapa hal keren seperti menambahkan metode baru ke kelas pada saat run time karena pencarian metode aktual ditangguhkan hingga saat terakhir. Kebanyakan orang menyebut keadaan ini sebagai ikatan yang mengikat.

Dalam bahasa yang diketik secara statis, variabel memiliki tipe dan setelah dideklarasikan tidak dapat merujuk ke nilai apa pun yang bukan dari tipe yang sama. Ini tidak sepenuhnya benar tetapi mari kita asumsikan untuk saat ini. Sekarang jika Anda tahu bahwa variabel hanya akan merujuk ke nilai-nilai dari tipe tertentu maka tidak ada alasan untuk mencari tahu apakah pemanggilan metode valid atau tidak saat dijalankan karena Anda dapat menentukan validitasnya sebelum kode dijalankan. Ini disebut sebagai pengikatan awal.

Contoh untuk menunjukkan keterlambatan pengikatan di ruby:

a = 1 # a is an integer at this point
a.succ # asking for its successor is valid

class A
  def method_a
    # some code
  end
end

a = A.new
a.method_a # this is also valid
a.succ # this is not valid


class A # we can re-open the class and add a method
  def succ
    # some more code
  end
end
a.succ # now this is valid

Urutan tindakan di atas tidak dimungkinkan dalam bahasa seperti Java di mana semua tipe diperbaiki pada saat dijalankan.


1

Alih-alih memberi Anda definisi akademis, saya akan mencoba menunjukkan kepada Anda beberapa perbedaan menggunakan contoh dunia nyata menggunakan VBA:

Ikatan awal:

Dim x As FileSystemObject
Set x = New FileSystemObject
Debug.Print x.GetSpecialFolder(0)

Ini membutuhkan referensi untuk disetel ke komponen "Microsoft Scripting Runtime" pada waktu desain . Ini memiliki keuntungan bahwa Anda sudah mendapatkan pesan kesalahan pada waktu kompilasi ketika Anda memiliki kesalahan ketik FileSystemObjectatau nama metode seperti GetSpecialFolder.

Mengikat terlambat

Dim x As Object
Set x = CreateObject("Scripting.FileSystemObject")
Debug.Print x.GetSpecialFolder(0)

Ini tidak memerlukan referensi untuk ditetapkan sebelumnya, pembuatan instance dan penentuan jenis hanya akan terjadi pada saat run-time. Kompiler tidak akan mengeluh pada waktu kompilasi ketika Anda mencoba memanggil metode yang tidak ada x, ini akan menyebabkan kesalahan run-time hanya ketika baris tertentu dijalankan.

Jadi, kelemahan dari pengikatan yang terlambat adalah Anda tidak memiliki pemeriksaan tipe yang kuat di sini. Tapi itu juga keuntungannya - katakanlah Anda memiliki komponen di mana beberapa versi ada, dan setiap versi yang lebih baru menyediakan beberapa fungsi tambahan. (Contoh dunia nyata adalah komponen MS Office, seperti antarmuka Excel COM) Pengikatan yang terlambat memungkinkan Anda menulis kode yang bekerja bersama dengan semua versi itu - Anda dapat menentukan versi komponen tertentu terlebih dahulu, dan jika Anda mengetahui bahwa Anda memiliki hanya versi lama yang tersedia, hindari untuk mengeksekusi fungsi panggilan yang tidak berfungsi dengan versi itu.


-2

Mungkin contoh paling umum dari pengikatan terlambat adalah menyelesaikan URL Internet. Ini mendukung sistem dinamis dan sistem besar tanpa mencoba untuk menautkan dan mengikat setiap situs di dunia sebelum Anda dapat mencapai apa pun, tetapi di sisi lain itu memang menimbulkan beberapa overhead (pencarian DNS, apalagi routing IP) saat runtime.

Dengan cahaya itu, sebagian besar jenis ikatan dalam lingkungan bahasa lebih atau kurang awal, pada waktu kompilasi atau waktu tautan.

Setiap jenis memiliki biaya dan manfaat.


Bisakah Anda menempatkan referensi untuk definisi pengikatan ini? Saya belum pernah mendengar tentang menyelesaikan alamat internet sebagai "mengikat", meskipun karena mengikat adalah tindakan penyelesaian nama, saya kira seseorang berpendapat bahwa konsep awal / akhir mengikat dapat diterapkan untuk menyelesaikan URI ke alamat internet. Tapi ini bukan interpretasi yang umum, dan konsep awal / akhir mengikat mendahului saat di mana komputer umumnya terhubung ke internet.
Jay Elston
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.