Duck typing — obyektning formal class yoki interface nomidan ko‘ra, kerakli operation va xatti-harakatni qo‘llab-quvvatlashiga qarab foydalanish usulidir. Atama “o‘rdakka o‘xshab yurib, o‘rdakdek ovoz chiqarsa, u o‘rdak” iborasidan keladi. Python va Ruby kabi dynamic tillarda keng tarqalgan, lekin structural typing bilan aynan bir tushuncha emas.
Xatti-harakatga tayanish
Function parameterning aniq classini tekshirmaydi, undan read, write yoki close methodini chaqiradi. File, memory buffer va network stream bir xil minimal protocolga mos bo‘lsa ishlaydi. Bu inheritance hierarchy’siz polymorphism beradi.
Nomning mavjudligi yetarli emas; semantika ham mos bo‘lishi kerak. read(size) byte qaytaradimi, end-of-streamni qanday bildiradi, exception va blocking xatti-harakati contractga kiradi. Duck typing ko‘pincha dokumentatsiya va test orqali shu protocolni ifodalaydi.
Dynamic va structural typing
Dynamic duck typing xatoni operation bajarilganda topadi. Static structural type esa obyekt kerakli memberlarga ega ekanini compile time’da tekshirishi mumkin. TypeScript interface’i nominal declaration talab qilmasdan shape bo‘yicha moslik beradi. Python Protocol gradual typing bilan duck contractni analyzerga ko‘rsatadi.
Reflection orqali “method bormi” deb oldindan tekshirish EAFP usulidan farq qiladi. Check bilan call orasida obyekt o‘zgarishi yoki descriptor exception berishi mumkin. Til idiomiga qarab operation bajarilib, faqat kutilgan exception ishlanadi. Juda keng exception ushlash method ichidagi haqiqiy bugni “qo‘llamaydi” deb yashirmaydi.
Afzalliklar
Kichik protocol couplingni kamaytiradi. Test double katta framework base classidan meros olmay, kerakli ikki methodni beradi. Adapter tashqi kutubxona obyektini consumer kutgan xatti-harakatga moslaydi. Yangi implementation eski callerni o‘zgartirmasdan qo‘shiladi.
Bu moslashuvchanlik plugin va utility kodda foydali. Biroq public API contract noaniq qolsa xato production’dagi kam ishlatiladigan pathda chiqadi. Type hint, runtime validation va contract test aniqlik beradi.
Xavflar
Ikki obyekt ayni method nomiga ega, lekin boshqa ma’no berishi accidental compatibility yaratadi. save() database commit yoki file write bo‘lishi mumkin. Aniq domain nomi va adapter konfliktni kamaytiradi. Return type va side effect hujjatlanadi.
Monkey patch runtime’da methodni almashtirsa debugging va security qiyinlashadi. Untrusted object property access paytida code bajarishi mumkin; serializer yoki template engine faqat “field bor” deb xavfsiz qabul qilmaydi. Sandbox va allowlist kerak.
API dizayni
Consumer eng kichik zarur protocolga tayanadi. Bir function o‘nlab method kutsa yashirin katta interface paydo bo‘ladi. Capabilitylar read, seek va close kabi alohida tekshirilishi mumkin. Optional operation aniq fallback yoki feature detectionga ega.
Testlar turli haqiqiy implementation, partial object va xato semantikasini qamrab oladi. Static type checker protocol mosligini erta topadi, runtime test esa behaviorni tasdiqlaydi. Duck typing “type muhim emas” degani emas; type nomidan ko‘ra xatti-harakat contracti muhimligini bildiradi.
Chegarada tekshirish
Duck typing ichki kodni moslashuvchan qilsa ham, tashqi API chegarasida noto‘g‘ri obyektni erta aniqlash foydali. Kerakli protokol hujjatda, type hint yoki strukturaviy interfeysda ifodalanadi. Shunda statik analizator chaqiruvdan oldin ko‘plab xatoni topadi, bajarish vaqtidagi erkinlik esa saqlanadi. Faqat metod mavjudligini tekshirish yetmasligi mumkin: uning parametr, natija va istisno shartnomasi ham mos bo‘lishi kerak. hasattr bilan uzun tekshiruvlar yozish o‘rniga amalni bajarib, aynan kutilgan xatoni ushlash ko‘pincha tabiiyroq. Biroq keng except haqiqiy ichki xatoni mos kelmaslik deb yashirmasligi zarur.
Bog‘liq tushunchalar
Structural typing, Dynamic typing, Protocol, Polymorphism, Adapter pattern, Method dispatch, Interface