Menu
Coddy logo textTech

Duck Typing

Coddy'nin Lua Journey'sinin Object Oriented Programming bölümünün bir parçası — ders 39 / 70.

Lua bir nesnenin sınıfını umursamaz; yalnızca nesnenin neler yapabildiğiyle ilgilenir. Bu kavram duck typing (ördek tiplemesi) olarak adlandırılır: "Eğer bir ördek gibi yürüyor ve bir ördek gibi vakvaklıyorsa, o bir ördektir." Programlama terimleriyle ifade etmek gerekirse, eğer bir nesne çağırdığınız metoda sahipse, çalışır.

Bu, aynı metot ismini paylaştıkları sürece tamamen ilgisiz sınıfların birlikte kullanılabileceği anlamına gelir:

local Circle = {}
Circle.__index = Circle
function Circle:new() 
    local obj = {}
    setmetatable(obj, Circle)
    return obj
end
function Circle:draw()
    print("Drawing a circle")
end

local Square = {}
Square.__index = Square
function Square:new()
    local obj = {}
    setmetatable(obj, Square)
    return obj
end
function Square:draw()
    print("Drawing a square")
end

Bu sınıfların hiçbir kalıtım ilişkisi yoktur; tamamen bağımsızdırlar. Yine de onlara aynı şekilde davranabiliriz:

local shapes = {Circle:new(), Square:new(), Circle:new()}

for _, shape in ipairs(shapes) do
    shape:draw()
end
-- Çıktı:
-- Bir daire çiziliyor
-- Bir kare çiziliyor
-- Bir daire çiziliyor

Döngü, her bir nesnenin hangi türde olduğunu kontrol etmez. Sadece :draw() metodunu çağırır ve metodun var olduğuna güvenir. Bu esneklik güçlüdür; döngü kodunu hiç değiştirmeden yeni şekil türleri ekleyebilirsiniz. Yeni sınıf :draw() metodunu uyguladığı sürece, sorunsuz çalışır.

challenge icon

Görev

Kolay

Hepsi aynı şekilde işlenebilen, tamamen ilgisiz sınıflarla bir bildirim sistemi oluşturarak duck typing'in gücünü gösterelim!

Üç bağımsız bildirim sınıfı oluşturacaksınız—hiçbiri birbirinden miras almaz—ancak hepsi bir :send() metodu uygular. Bu, karışık bir koleksiyon içinde döngü kurabileceğiniz ve gerçek türünü önemsemeden her biri üzerinde :send() metodunu çağırabileceğiniz anlamına gelir.

Kodunuzu dört dosya halinde düzenleyeceksiniz:

  • Email.lua: E-postanın kime gideceğini saklayan bir :new(recipient) kurucusuna sahip bir sınıf. :send() metodu Emailing {recipient} yazdırmalıdır.
  • SMS.lua: :new(phoneNumber) kurucusuna sahip tamamen ayrı bir sınıf. :send() metodu Texting {phoneNumber} yazdırmalıdır.
  • PushNotification.lua: :new(deviceId) kurucusuna sahip başka bir bağımsız sınıf. :send() metodu Pushing to {deviceId} yazdırmalıdır.
  • main.lua: Her şeyi bir araya getirin! Üç girdi okuyun, her bildirim türünden birer örnek oluşturun, hepsini tek bir tabloya koyun, ardından tabloyu döngüye sokun ve her biri üzerinde :send() metodunu çağırın.

Üç girdi alacaksınız:

  1. Bir e-posta alıcısı (örneğin, alice@example.com)
  2. Bir telefon numarası (örneğin, 555-1234)
  3. Bir cihaz kimliği (örneğin, device_99)

Ana dosyanızda, her üç bildirim nesnesini de oluşturun, bunları bir tabloda saklayın ve tablo üzerinde gezinerek her biri için :send() metodunu çağırın. Sıralama şu şekilde olmalıdır: Önce Email, sonra SMS, ardından PushNotification.

Örneğin, girdiler bob@mail.com, 555-9876 ve phone_42 ise, çıktı şu şekilde olmalıdır:

Emailing bob@mail.com
Texting 555-9876
Pushing to phone_42

Döngünüzün her nesnenin hangi türde olduğunu kontrol etmesine gerek kalmadığına dikkat edin—sadece koleksiyondaki her nesnenin bir :send() metoduna sahip olduğuna güvenir. İşte bu, iş başındaki duck typing'dir! Eğer :send() yapabiliyorsa, o bir bildirimdir.

Kopya kağıdı

Lua duck typing (ördek tiplemesi) kullanır: Eğer bir nesne çağırdığınız metoda sahipse, sınıfı ne olursa olsun çalışır. İlke şudur: "Eğer bir ördek gibi yürüyorsa ve bir ördek gibi vakvaklıyorsa, o bir ördektir."

Tamamen ilgisiz sınıflar, aynı metod ismini paylaştıkları sürece birbirlerinin yerine kullanılabilirler:

local Circle = {}
Circle.__index = Circle
function Circle:new() 
    local obj = {}
    setmetatable(obj, Circle)
    return obj
end
function Circle:draw()
    print("Drawing a circle")
end

local Square = {}
Square.__index = Square
function Square:new()
    local obj = {}
    setmetatable(obj, Square)
    return obj
end
function Square:draw()
    print("Drawing a square")
end

Bu sınıfların aralarında bir kalıtım ilişkisi yoktur, ancak yine de aynı şekilde ele alınabilirler:

local shapes = {Circle:new(), Square:new(), Circle:new()}

for _, shape in ipairs(shapes) do
    shape:draw()
end
-- Çıktı:
-- Drawing a circle
-- Drawing a square
-- Drawing a circle

Döngü nesne türlerini kontrol etmez; sadece metodu çağırır ve var olduğuna güvenir. Gerekli metodu uyguladıkları sürece, mevcut kodu değiştirmeden yeni türler ekleyebilirsiniz.

Kendin dene

-- main.lua
-- Tüm bildirim türlerini bir araya getirin ve duck typing (ördek tipleme) yöntemini gösterin

-- Bildirim sınıflarını içe aktarın
local Email = require('Email')
local SMS = require('SMS')
local PushNotification = require('PushNotification')

-- Girdileri oku
local recipient = io.read()
local phoneNumber = io.read()
local deviceId = io.read()

-- TODO: Her bildirim türünden birer örnek oluşturun

-- TODO: Tüm bildirimleri tek bir tabloya koyun (Önce Email, sonra SMS, sonra PushNotification)

-- TODO: Tablo üzerinde döngü kurun ve her bildirim için :send() metodunu çağırın
-- Bu, duck typing'i gösterir - türü kontrol etmeyiz, sadece :send() metodunu çağırırız
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Object Oriented Programming bölümündeki tüm dersler