Menu
Coddy logo textTech

Mixin'ler ve Kalıtım

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

Davranış paylaşmanın iki yolunu öğrendiniz: kalıtım prototip zinciri aracılığıyla bir "is-a" ilişkisi oluştururken, mixin'ler fonksiyonları doğrudan bir sınıfa kopyalar. Peki, her bir yaklaşımı ne zaman kullanmalısınız?

Nesneler temel bir kimliği paylaştığında kalıtım kullanın. Bir Bird bir Animal'dır—Bird'ün :eat() veya :sleep() gibi temel hayvan davranışlarını miras alması mantıklıdır. Bu ilişki kalıcıdır ve nesnenin temel olarak ne olduğunu tanımlar.

Nesnenin temel kimliğini tanımlamayan bir yetenek eklemek istediğinizde mixin'leri kullanın.

Tüm kuşlar uçamaz; penguenler ve deve kuşları kuştur ancak uçmazlar. Uçmak bir yetenektir, kuş olmanın tanımlayıcı bir özelliği değildir. Bir Flyable mixin'i, tüm kuşlara zorunlu kılmadan, ihtiyacı olan kuşlara uçma yeteneği eklemenizi sağlar.

Bu iki yaklaşım birlikte mükemmel bir şekilde çalışır:

-- Bird, Animal'dan miras alır (is-a ilişkisi)
local Bird = {}
Bird.__index = Bird
setmetatable(Bird, {__index = Animal})

-- Flyable bir yetenektir (mixin)
local Flyable = {}
function Flyable:fly()
    print(self.name .. " soars through the sky!")
end

-- Mixin'i sadece uçabilen kuşlara uygula
applyMixin(Bird, Flyable)

Bu desen size her iki dünyanın da en iyisini sunar: ortak kimlik için net bir sınıf hiyerarşisi ve ihtiyaç duyulan yerlerde eklenebilen esnek yetenekler.

challenge icon

Görev

Kolay

Kalıtım (inheritance) ile mixin'lerin ne zaman kullanılacağını gösteren küçük bir canlı ekosistemi inşa edelim! Bir Animal temel sınıfı, ondan kalıtım alan bir Bird sınıfı ve bir Swimmable mixin'i oluşturacaksınız; çünkü tüm kuşlar hayvandır, ancak tüm kuşlar yüzemez.

Kodunuzu dört dosya halinde düzenleyeceksiniz:

  • Animal.lua: İsmi saklayan bir :new(name) yapıcı metoduna (constructor) sahip temel Animal sınıfını oluşturun. {name} is eating çıktısını veren bir :eat() metodu ekleyin. Bu, tüm hayvanların paylaştığı temel kimliği temsil eder.
  • Swimmable.lua: {self.name} is swimming çıktısını veren bir :swim() metoduna sahip bir mixin oluşturun. Bu bir yetenektir; tüm canlılar yüzemez, bu yüzden kalıtım zincirinin bir parçası olmamalıdır.
  • Bird.lua: Animal sınıfından kalıtım alan bir Bird sınıfı oluşturun. :new(name, canSwim) yapıcı metodu, üst sınıfın yapıcı metodunu çağırmalı ve bu kuşun yüzüp yüzemeyeceğini saklamalıdır. Swimmable mixin'ini Bird sınıfına uygulayın. {name} chirps! çıktısını veren bir :chirp() metodu ekleyin; bu, kuşa özgü bir davranıştır.
  • main.lua: applyMixin yardımcı fonksiyonunu burada yazın. Bir kuşun adı ve yüzüp yüzemediği (yes veya no) için girdileri okuyun. Bir Bird örneği oluşturun, ardından yeteneklerini sergileyin: :eat() (Animal'dan kalıtım alınan), :chirp() (Bird'ün kendi metodu) metodlarını çağırın ve yalnızca kuş yüzebiliyorsa :swim() metodunu çağırın.

İki girdi alacaksınız:

  1. Kuşun adı (bir dize)
  2. Kuşun yüzüp yüzemediği: yes veya no

Eğer kuş yüzebiliyorsa, çıktınız şu şekilde olmalıdır:

{name} is eating
{name} chirps!
{name} is swimming

Eğer kuş yüzemiyorsa, çıktınız şu şekilde olmalıdır:

{name} is eating
{name} chirps!

Örneğin, girdiler Duck ve yes ise, çıktı şu şekilde olmalıdır:

Duck is eating
Duck chirps!
Duck is swimming

Girdiler Sparrow ve no ise, çıktı şu şekilde olmalıdır:

Sparrow is eating
Sparrow chirps!

Bu zorluk temel ayrımı göstermektedir: Bird bir Animal'dır (kalıtım), ancak yüzme isteğe bağlı bir yetenektir (mixin). Mixin sınıfa uygulanır, ancak ana mantığınız bunu bireysel kuşun yeteneklerine göre kullanıp kullanmamaya karar verir!

Kopya kağıdı

Nesneler temel bir kimliği paylaştığında (bir "is-a" ilişkisi) kalıtım kullanın. Nesnenin temel kimliğini tanımlamayan yetenekler eklerken mixin'ler kullanın.

Kalıtım, prototip zinciri aracılığıyla kalıcı bir ilişki oluşturur:

local Bird = {}
Bird.__index = Bird
setmetatable(Bird, {__index = Animal})

Mixin'ler, seçici olarak uygulanabilen isteğe bağlı yetenekler ekler:

local Flyable = {}
function Flyable:fly()
    print(self.name .. " soars through the sky!")
end

applyMixin(Bird, Flyable)

İki yaklaşım birlikte çalışır: paylaşılan kimlik için kalıtımı, yalnızca bazı örneklerin ihtiyaç duyduğu esnek yetenekler için ise mixin'leri kullanın.

Kendin dene

-- main.lua: Giriş noktası - bir kuş oluşturun ve yeteneklerini gösterin

-- Bir sınıfa mixin uygulamak için yardımcı fonksiyon
local function applyMixin(class, mixin)
    -- TODO: Mixin'deki tüm metotları sınıfa kopyalayın
    
end

-- Bird'ü require etmeden önce Swimmable mixin'ini Bird'e uygulayın
-- Not: Bunu Bird.lua içinde veya burada halletmeniz gerekebilir

local Bird = require('Bird')
local Swimmable = require('Swimmable')

-- Mixin'i Bird sınıfına uygula
applyMixin(Bird, Swimmable)

-- Girdileri oku
local name = io.read()
local canSwimInput = io.read()

-- TODO: Girdiye göre kuşun yüzüp yüzemeyeceğini belirleyin ("yes" veya "no")

-- TODO: İsim ve yüzme yeteneği ile bir Bird örneği oluşturun

-- TODO: eat() metodunu çağırın - Animal sınıfından miras alınmıştır

-- TODO: chirp() metodunu çağırın - Bird sınıfının kendi metodu

-- TODO: swim() metodunu sadece kuş yüzebiliyorsa çağırın
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