Saya menemukan istilah mengetik bebek sambil membaca topik acak pada perangkat lunak online dan tidak sepenuhnya memahaminya.
Apa itu "mengetik bebek"?
Saya menemukan istilah mengetik bebek sambil membaca topik acak pada perangkat lunak online dan tidak sepenuhnya memahaminya.
Apa itu "mengetik bebek"?
Jawaban:
Ini adalah istilah yang digunakan dalam bahasa dinamis yang tidak memiliki ketikan yang kuat .
Idenya adalah bahwa Anda tidak perlu tipe untuk memohon metode yang ada pada objek - jika metode didefinisikan, Anda dapat memohonnya.
Namanya berasal dari ungkapan "Jika terlihat seperti bebek dan dukun seperti bebek, itu bebek".
Wikipedia memiliki lebih banyak informasi.
Mengetik bebek berarti bahwa suatu operasi tidak secara formal menentukan persyaratan yang harus dipenuhi operandnya, tetapi hanya mencobanya dengan apa yang diberikan.
Tidak seperti apa yang dikatakan orang lain, ini tidak selalu berhubungan dengan bahasa yang dinamis atau masalah warisan.
Contoh tugas: Memanggil beberapa metode Quack
pada objek.
Tanpa menggunakan bebek-mengetik, fungsi f
melakukan tugas ini harus menentukan terlebih dahulu bahwa argumennya harus mendukung beberapa metode Quack
. Cara yang umum adalah penggunaan antarmuka
interface IQuack {
void Quack();
}
void f(IQuack x) {
x.Quack();
}
Panggilan f(42)
gagal, tetapi f(donald)
berfungsi selama donald
merupakan instance dari IQuack
-subtype.
Pendekatan lain adalah pengetikan struktural - tetapi sekali lagi, metode Quack()
ini secara formal menentukan segala hal yang tidak dapat membuktikannya quack
terlebih dahulu akan menyebabkan kegagalan kompiler.
def f(x : { def Quack() : Unit }) = x.Quack()
Kami bahkan bisa menulis
f :: Quackable a => a -> IO ()
f = quack
di Haskell, di mana Quackable
typeclass memastikan keberadaan metode kami.
Yah, seperti yang saya katakan, sistem mengetik bebek tidak menentukan persyaratan tetapi hanya mencoba jika ada yang berhasil .
Dengan demikian, sistem tipe dinamis seperti Python selalu menggunakan mengetik bebek:
def f(x):
x.Quack()
Jika f
mendapat x
dukungan Quack()
, semuanya baik-baik saja, jika tidak, itu akan macet saat runtime.
Tetapi mengetik bebek tidak menyiratkan mengetik dinamis sama sekali - pada kenyataannya, ada pendekatan mengetik bebek yang sangat populer tetapi benar-benar statis yang tidak memberikan persyaratan apa pun juga:
template <typename T>
void f(T x) { x.Quack(); }
Fungsi tidak mengatakan dengan cara apa pun bahwa ia menginginkan beberapa x
yang bisa Quack
, jadi alih-alih hanya mencoba pada waktu kompilasi dan jika semuanya berfungsi, itu baik-baik saja.
def f(x)
bukannya def f(IQuack x)
.
Diskusi semantik dari pertanyaan ini cukup bernuansa (dan sangat akademis), tapi inilah ide umum:
Mengetik Bebek
(“Jika berjalan seperti bebek dan dukun seperti bebek maka itu adalah bebek.”) - YA! tapi apa artinya itu ??! Ini paling baik digambarkan dengan contoh:
Contoh fungsionalitas Mengetik Bebek:
Bayangkan saya punya tongkat sihir. Ia memiliki kekuatan khusus. Jika saya melambaikan tongkat dan berkata "Berkendara!" ke mobil, lalu, itu drive!
Apakah ini berhasil pada hal lain? Tidak yakin: jadi saya mencobanya di truk. Wow - itu drive juga! Saya kemudian mencobanya di pesawat, kereta api dan 1 Woods (mereka adalah jenis klub golf yang digunakan orang untuk 'menggerakkan' bola golf). Mereka semua mengemudi!
Tetapi apakah itu akan berhasil pada kata, cangkir teh? Kesalahan: KAAAA-BOOOOOOM! itu tidak berhasil begitu baik. ====> Cangkir teh tidak bisa mengemudi !! ya !?
Ini pada dasarnya konsep mengetik bebek. Ini adalah sistem coba-sebelum-Anda-beli . Jika berhasil, semuanya baik-baik saja. Tetapi jika gagal, seperti granat masih di tangan Anda, itu akan meledak di wajah Anda.
Dengan kata lain, kita tertarik pada apa yang bisa dilakukan objek , daripada dengan apa objek itu .
Contoh: bahasa yang diketik secara statis
Jika kita khawatir dengan apa objek itu sebenarnya , maka trik sulap kita hanya akan bekerja pada tipe yang telah ditentukan sebelumnya - dalam hal ini mobil, tetapi akan gagal pada objek lain yang dapat mengemudi : truk, moped, tuk-tuk, dll. Ini tidak akan berfungsi pada truk karena tongkat sihir kami mengharapkannya hanya bekerja pada mobil .
Dengan kata lain, dalam skenario ini, keajaiban tongkat terlihat sangat erat pada apa benda itu adalah (itu mobil?) Daripada apa benda dapat melakukan (misalnya apakah mobil, truk dll bisa berkendara).
Satu-satunya cara Anda bisa mendapatkan truk untuk dikendarai adalah jika Anda entah bagaimana bisa mendapatkan tongkat ajaib untuk mengharapkan truk dan mobil (mungkin dengan "menerapkan antarmuka umum"). Jika Anda tidak tahu apa artinya itu maka abaikan saja untuk saat ini.
Ringkasan: Pengambilan kunci
Apa yang penting dalam mengetik bebek adalah apa benda itu benar-benar dapat lakukan, bukan apa benda itu adalah .
Anggap Anda sedang mendesain fungsi sederhana, yang mendapatkan objek bertipe Bird
dan memanggil walk()
metodenya. Ada dua pendekatan yang dapat Anda pikirkan:
Bird
, atau kode mereka tidak akan dikompilasi. Jika ada yang ingin menggunakan fungsi saya, ia harus sadar bahwa saya hanya menerima Bird
sobjects
dan saya hanya memanggil walk()
metode objek. Jadi, jika object
bisa walk()
itu benar, jika tidak bisa fungsi saya akan gagal. Jadi di sini tidak penting objeknya adalah Bird
sesuatu atau apa pun, penting bahwa itu bisa walk()
(Ini adalah mengetik bebek )Harus dipertimbangkan bahwa mengetik bebek mungkin berguna dalam beberapa kasus, misalnya Python menggunakan banyak mengetik bebek .
Wikipedia memiliki penjelasan yang cukup rinci:
http://en.wikipedia.org/wiki/Duck_typing
duck typing adalah gaya pengetikan dinamis di mana serangkaian metode dan properti objek saat ini menentukan semantik yang valid, bukan warisannya dari kelas tertentu atau implementasi antarmuka tertentu.
Catatan penting adalah kemungkinan bahwa dengan mengetik bebek pengembang lebih mementingkan bagian-bagian dari objek yang dikonsumsi daripada apa yang mendasari tipe sebenarnya.
Saya melihat banyak jawaban yang mengulangi ungkapan lama:
Jika terlihat seperti bebek dan dukun seperti bebek, itu bebek
dan kemudian terjun ke penjelasan tentang apa yang dapat Anda lakukan dengan mengetik bebek, atau contoh yang tampaknya mengaburkan konsep lebih lanjut.
Saya tidak menemukan banyak bantuan.
Ini adalah upaya terbaik untuk jawaban bahasa Inggris yang sederhana tentang mengetik bebek yang saya temukan:
Mengetik Bebek berarti bahwa suatu objek ditentukan oleh apa yang dapat dilakukannya, bukan oleh apa itu.
Ini berarti bahwa kita kurang peduli dengan kelas / jenis objek dan lebih peduli dengan metode apa yang dapat dipanggil dan operasi apa yang dapat dilakukan di atasnya. Kami tidak peduli dengan tipenya, kami peduli dengan apa yang bisa dilakukannya .
Mengetik bebek:
Jika berbicara dan berjalan seperti bebek, maka itu adalah bebek
Ini biasanya disebut penculikan ( abductive reasoning atau juga disebut retroduction , menurut saya definisi yang lebih jelas):
dari C (kesimpulan, apa yang kita lihat ) dan R (aturan, apa yang kita ketahui ), kita menerima / memutuskan / menganggap P (Premis, properti ) dengan kata lain fakta yang diberikan
... dasar diagnosis medis
dengan bebek: C = berjalan, berbicara , R = seperti bebek , P = itu bebek
Kembali ke pemrograman:
objek o memiliki metode / properti mp1 dan antarmuka / tipe T membutuhkan / mendefinisikan mp1
objek o memiliki metode / properti mp2 dan antarmuka / tipe T membutuhkan / mendefinisikan mp2
...
Jadi, lebih dari sekadar menerima mp1 ... pada objek apa pun asalkan telah memenuhi beberapa definisi mp1 ..., compiler / runtime juga harus baik-baik saja dengan pernyataan o adalah tipe T
Dan baiklah, apakah demikian halnya dengan contoh-contoh di atas? Apakah mengetik Bebek pada dasarnya tidak mengetik sama sekali? Atau haruskah kita menyebutnya pengetikan tersirat?
Melihat bahasa itu sendiri dapat membantu; itu sering membantu saya (saya bukan penutur bahasa Inggris asli).
Dalam duck typing
:
1) kata typing
itu tidak berarti mengetik pada keyboard (seperti gambar yang terus-menerus ada dalam pikiran saya), itu berarti menentukan " jenis benda apa itu? "
2) kata tersebut duck
mengungkapkan bagaimana penentuan itu dilakukan; itu semacam penentu 'longgar', seperti dalam: " jika berjalan seperti bebek ... maka itu bebek ". Ini 'longgar' karena benda itu mungkin bebek atau bukan, tetapi apakah itu sebenarnya bebek, tidak masalah; yang penting adalah saya bisa melakukannya dengan apa yang bisa saya lakukan dengan bebek dan mengharapkan perilaku yang ditunjukkan oleh bebek. Saya bisa memberi makan remah roti dan hal itu mungkin pergi ke arah saya atau menagih ke saya atau mundur ... tapi itu tidak akan melahap saya seperti yang grizzly.
Saya tahu saya tidak memberikan jawaban umum. Di Ruby, kami tidak mendeklarasikan jenis variabel atau metode — semuanya hanya semacam objek. Jadi Aturannya adalah "Kelas Bukan Jenis"
Di Ruby, kelasnya bukan tipe (OK, hampir tidak pernah). Sebaliknya, jenis objek lebih ditentukan oleh apa yang bisa dilakukan objek itu. Di Ruby, kami menyebutnya mengetik bebek. Jika suatu benda berjalan seperti bebek dan berbicara seperti bebek, maka penerjemah dengan senang hati memperlakukannya seolah-olah itu adalah bebek.
Misalnya, Anda mungkin menulis rutin untuk menambahkan informasi lagu ke string. Jika Anda berasal dari latar belakang C # atau Java, Anda mungkin tergoda untuk menulis ini:
def append_song(result, song)
# test we're given the right parameters
unless result.kind_of?(String)
fail TypeError.new("String expected") end
unless song.kind_of?(Song)
fail TypeError.new("Song expected")
end
result << song.title << " (" << song.artist << ")" end
result = ""
append_song(result, song) # => "I Got Rhythm (Gene Kelly)"
Merangkul mengetik bebek Ruby, dan Anda akan menulis sesuatu yang jauh lebih sederhana:
def append_song(result, song)
result << song.title << " (" << song.artist << ")"
end
result = ""
append_song(result, song) # => "I Got Rhythm (Gene Kelly)"
Anda tidak perlu memeriksa jenis argumen. Jika mereka mendukung << (dalam hal hasil) atau judul dan artis (dalam hal lagu), semuanya akan berfungsi dengan baik. Jika tidak, metode Anda akan memunculkan pengecualian (seperti yang akan dilakukan jika Anda memeriksa jenisnya). Tetapi tanpa pemeriksaan, metode Anda tiba-tiba jauh lebih fleksibel. Anda bisa memberikannya array, string, file, atau objek lain yang ditambahkan menggunakan <<, dan itu hanya akan berfungsi.
Mengetik Bebek bukan Tipe Petunjuk!
Pada dasarnya untuk menggunakan "mengetik bebek" Anda tidak akan menargetkan jenis tertentu tetapi lebih banyak subtipe (tidak berbicara tentang warisan, ketika saya maksudkan subtipe yang saya maksudkan "hal-hal" yang sesuai dengan profil yang sama) dengan menggunakan antarmuka umum .
Anda dapat membayangkan suatu sistem yang menyimpan informasi. Untuk menulis / membaca informasi, Anda memerlukan semacam penyimpanan dan informasi.
Jenis penyimpanan mungkin: file, basis data, sesi dll.
Antarmuka akan memberi tahu Anda opsi (metode) yang tersedia terlepas dari jenis penyimpanannya, artinya pada saat ini tidak ada yang diterapkan! Dengan kata lain Antarmuka tidak tahu apa-apa tentang cara menyimpan informasi.
Setiap sistem penyimpanan harus mengetahui keberadaan antarmuka dengan menerapkan metode yang sangat sama.
interface StorageInterface
{
public function write(string $key, array $value): bool;
public function read(string $key): array;
}
class File implements StorageInterface
{
public function read(string $key): array {
//reading from a file
}
public function write(string $key, array $value): bool {
//writing in a file implementation
}
}
class Session implements StorageInterface
{
public function read(string $key): array {
//reading from a session
}
public function write(string $key, array $value): bool {
//writing in a session implementation
}
}
class Storage implements StorageInterface
{
private $_storage = null;
function __construct(StorageInterface $storage) {
$this->_storage = $storage;
}
public function read(string $key): array {
return $this->_storage->read($key);
}
public function write(string $key, array $value): bool {
return ($this->_storage->write($key, $value)) ? true : false;
}
}
Jadi sekarang, setiap kali Anda perlu menulis / membaca informasi:
$file = new Storage(new File());
$file->write('filename', ['information'] );
echo $file->read('filename');
$session = new Storage(new Session());
$session->write('filename', ['information'] );
echo $session->read('filename');
Dalam contoh ini Anda akhirnya menggunakan konstruktor Duck Typing in Storage:
function __construct(StorageInterface $storage) ...
Semoga ini bisa membantu;)
Saya pikir itu bingung untuk mencampur pengetikan dinamis, pengetikan statis dan pengetikan bebek. Mengetik bebek adalah konsep independen dan bahkan bahasa yang diketik statis seperti Go, dapat memiliki sistem pengecekan tipe yang mengimplementasikan pengetikan bebek. Jika sistem tipe akan memeriksa metode objek (dideklarasikan) objek tetapi bukan tipenya, ini bisa disebut bahasa pengetikan bebek.
Saya mencoba memahami kalimat terkenal dengan cara saya: "Dosis ular sanca tidak peduli objek adalah bebek nyata atau tidak. Yang penting adalah apakah objek, pertama 'dukun', kedua 'seperti bebek'."
Ada situs web yang bagus. http://www.voidspace.org.uk/python/articles/duck_typing.shtml#id14
Penulis menunjukkan bahwa mengetik bebek memungkinkan Anda membuat kelas Anda sendiri yang memiliki struktur data internal sendiri - tetapi diakses menggunakan sintaksis Python normal.