Ruby’de Modül Yapısı – 2

Merhabalar bir Önceki yazımızda module kavramına değinmiş ve basit anlamda kullanımını işlemiş be bu yazımızda da çok güzel bir mudule mixin Örneği olduğunu sÖylemiştik. Şimdiki yazımızda Module kavramını daha da derinden işleyeceğiz.

Öncelikle module ile class arasındaki farktan bahsedelim. Evet fark diyorum çünkü sadece bir-iki küçük fark var. Elbette temelde birbirinden çok farklı yapılar ama, son kullanıcı yani bizler için aralarındaki fark at ile deve değil.
– class’ların anlık kopyaları olabilir, module’lerin olamaz.
– class’ların içerisinde module’ler olamaz, module’lerin içerisinde class’lar olabilir.
– class’lar ve içlerindeki Öğeler protected, private gibi erişim denetleyici Özelliklere sahip olabilirler, module’ler sahip olamazlar, tüm Öğeleri public’tir.

Class ile module’ler arasındaki temel farkları inceledikten sonra module mixin kavramı ile ilgili konuşmalarımıza başlayabiliriz. Yazının geri kalanında kullanılacak bir hatırlatma yapmak isterim.
[ruby]
class LogClass
NAME = “Default Class”

def LogClass.create # static create method
printf “%s LogHelper.create\n”, NAME
end

def create # instance create method
printf “%s LogHelper.create\n”, NAME
end
end
[/ruby]
Yukarıda belirtildiği gibi, “LogClass.create” methodu ile “create” methodu birbirinden farklıdır. “LogClass.create” methodu durağan (static, kullanmak için bir nesneye ihtiyaç duyulmaz.) bir method iken, “create” methodu kullanmak için “LogClass.new” methodu ile yeni bir “LogClass” yaratmalı ve bu nesne üzerinden “create” methoduna erişmeliyiz.

Bu bilgilerin ışığında aşağıdaki gibi tanıtılmış olan bir LogHelper modülünde
[ruby]
module LogHelper
NAME = “Default Logger”

def LogHelper.create
printf “%s LogHelper.create\n”, NAME
end
….
end
[/ruby]
tüm methodların durağan (static) olduğunu sÖyleyebiliriz.

Peki “module mixin” kullandığımızda sadece durağan (static) methodlar için mi kullanabileceğiz, elbetteki hayır. “Module mixin” Özelliğini tüm durumlar için kullanabiliriz.
Hemen Örneğimizi verelim;
[ruby]
module LogHelper # Module mixin işemi için
NAME = “Default Logger”

def error # LogHelper’da dinamik bir method
printf “%s #{self}.error\n”, NAME
@operationList.push(“error”)
end

def self.myTest # LogHelper’da durağan bir method
printf “%s #{self}.myTest(Static)\n”, NAME
end

def myTest # LogHelper’da dinamik bir method
printf “%s #{self}.myTest(Instance)\n”, NAME
LogHelper.myTest # LogHelper’daki static method çağrılir.
@operationList.push(“myTest”)
end
end

class LogClass
# LogHelper modülü sanki copy-paste edilmiş gibi bu sınıfın içerisinde yer alir.
# LogHelper üzerinden static olmayan methodlar alınır.
include LogHelper
attr_reader :operationList

def initialize # LogClass’in yapıcısı
@operationList = Array.new
end

def ownMethod # LogClass’in dinamik bir methodu
printf “%s #{self}.OwnMethod\n”, NAME
@operationList.push(“OwnMethod”)
end
end

# İşlemleri biraz daha karmaşıklaştırmak için ayrı bir modül içerisinde program yazılmiştır.
module LogProgram
logClass = LogClass.new # Yeni bir LogClass yaratılır.
logClass.ownMethod # LogClass’ın methodu cağrılır.
logClass.error # LogClass üzerinden LogHelper’in methodu çağrilir. Ama LogClass’in değişkenleri kullanılır.
logClass.myTest # error’u çağırmaktan tek farkı, myTest içerisinde static olan LogHelper.myTest’in cağırılmasıdır.

LogHelper.myTest # Static olan LogHelper.myTest çağrılır.

# Bu işlem için Ruby bize “warning: toplevel constant Y referenced by X::Y” uyarısını verir.
# Uyarı vermesinin nedeni işlemi garip ve tehlikeli şekilde yapıyor olmamızdır.
LogClass::LogHelper.myTest

# Yapilmiş işlemler ekrana yazdırılır.
puts logClass.operationList
end
[/ruby]
Yukarıda program işlendikten sonra ekrana;
Default Logger #.OwnMethod
Default Logger #.error
Default Logger #.myTest(Instance)
Default Logger LogHelper.myTest(Static)
Default Logger LogHelper.myTest(Static)
Default Logger LogHelper.myTest(Static)
OwnMethod
error
myTest
module02.rb:41: warning: toplevel constant LogHelper referenced by LogClass::LogHelper

çıktısını vermektedir.

Sonuç olarak mudule mixin kavramı, yazdığımız modülün static methodlarını copy-paste etmişcesine kullandığımız sınıfın içerisine kopyalanması gibi düşünebiliriz. Bu Özellikle ‘multiple inheritance’ kavramının eksikliği ustaca giderilmiştir.

Umarım bu yazıyı okuduktan sonra, Rails üzerinde yazdığınız uygulamara daha farklı yaklaşırsınız, işin aslı ruby on rails alt yapısı, büyük Ölçüde bu felsefe ve Özelliği kullanan bir yapıdır.

Kolay gelsin :)

Share