Selam,
Yazının 2. bölümünde sınıflarla devam ediyoruz.
Sınıflar
Bu kısımla ilgili daha değişik bilgileri tercüme ettiğim Wikibooks/Ruby/Sınıflar sayfasında da bulabilirsiniz.
Bir sınıf tanımlamanın deyim yapısı.
Ruby'de sınıf isimleri, veri tipi olarak sabitlerdir, o yüzden büyük harfle başlamaları gerekir.
-- Üretici metod
Bir sınıfta sadece bir tane üretici metod olabilir ve adı initialize olur. Bu metod sınıftan yeni bir nesne üretildiğinde otomatik olarak çağrılır.
-- Bir sınıf tanımlamak
class ifadesi ile sınıf tanımlaması yapılır.
Bir kere tanımlandıktan sonra sınıfın new metodu kullanılarak nesne oluşumları üretilir.
-- Erişim seviyeleri
Ruby'de 3 tane erişim seviyesi vardır: public, private ve protected.
private veya protected ifadelerinden sonra tanımlanan metodlar, o gruba aittir. Bunlardan önce tanımlanmış olan metodlar ise default olarak public'tir.
-- -- public metodlar
Public metodlar üretilen nesnenin davranışlarını belirlerler. Bu metodlar üretilen nesnenin dışında kalan kapsamdan çağrılabilir.
Bu metodlar public, yeni Kedi nesnesi oluştururken ve o nesneyi konuştururken davranışını belirliyor (initialize ve konuş metodları).
public ifadesi gereksizdir, ama bazen private ya da protected bölümden çıkmak için kullanılabilir.
-- -- private metodlar
Private metodlara nesne dışından erişilemez. Nesne içinde kullanılan metodlardır. Kedi örneğimize dönelim.
Gördüğünüz üzere yeni oluşturulan kedi nesnesi kedi_yaşı_hesapla private metoduna kendi içinde erişebiliyor. Metoddan dönen değeri yaş yerel değişkenine saklıyoruz ve kullanıyoruz.
Ancak kedi_yaşı_hesapla metodunu yeni_kedi nesnesi dışında kullanmaya kalktığımızda bir NoMethodError hatası alıyoruz.
Yine de private metoda ulaşmanın bir yolu var, send ile nesneye mesaj göndererek metodu çağırmak.
belki lazım olur.
-- -- protected metodlar
Protected metodlar ve private metodlar birbirine oldukça benzer, onlara da nesne dışından erişilemez. Ancak protected metodlara aynı sınıftan üretilen diğer nesnelerden ulaşılabilir. Bir örnekle açıklamaya çalışalım.
Yeni bir Kedi nesnesi oluştururken parametrelere bir de yaş değeri ilave ettik. Kedilerimizin yaşlarını karşılaştırırken protected olan kendi_yaşı metodunu kullanıyoruz.
Aynı sınıftan başka bir nesnenin protected metoduna diğer.kendi_yaşı şeklinde erişebiliyoruz. Ama
dışarıdan bu metoda ulaşılamaz.
-- Oluşum değişkenlerine okuyucu ve yazıcı metodlarla erişmek
3 tane metodumuz vardır.
- attr_reader : nesne dışından oluşum değişkenini okumak için
- attr_writer : nesne dışından oluşum değişkenine yazmak için
- attr_accessor : her iki metodun birleşimi
Örnek :
Metodlarımıza parametre olarak semboller verdik, bunlar metodlar üretir. Mesela
Kodu irb oturumunda denediğimizde aslında bize cins ve cins= metodlarının üretildiğini söylüyor. Bu kod temelde şu kodla aynı işi yapar:
Deneyelim
Burada dikkat çeken şeylerden biri cins= metodunu cins = şeklinde boşlukla ayrılmış yazabiliyoruz. Bu Ruby'nin eşittir işareti ile biten metodlara uyguladığı bir ayrıcalık. Bu sayede diğer birçok dilde olduğu gibi get,set metodları gibi şeylerle veya property tanımlamaları ile uğraşmıyoruz.
Dikkat edilmesi gereken bir nokta da mesela attr_accessor :cins dediğimizde oluşum değişkeni olan @cins değişkenine erişmekten bahsediyoruz, @ işaretinin yokluğu sizi yanıltmasın, Ruby'de oluşum değişkenleri @ ile başlamak zorundadır.
Yine de oluşum değişken değerlerini işlerken standart dışı bir işlem yapacaksak, mesela bir değer doğrulaması yapacaksak, kendi metodlarımızı el ile tanımlamayı tercih edebiliriz.
gibi.
-- Sınıf metod tipleri
Sınıf metodu , oluşum metodu ve tekil metod olarak 3 değişik metod tanımlanabilir.
-- -- Oluşum metodları
Bu metodlar şimdiye kadar gördüklerimiz, ve sınıfın oluşum nesneleri kapsamında çağrılırlar.
-- -- Sınıf metodları
Bu metodlar sınıfın statik metodlarıdır ve oluşum nesnelerinden çağrılamazlar.
Metod ismi başına sınıfın adını ve nokta koyarak bir sınıf metodu olduğunu belirtiyoruz. İstersek sınıf adı yerine self de koyabiliriz.
self kelimesi sınıf kapsamındayken sınıfı, oluşum metodu içindeyken de oluşum nesnesini ifade eder.
Bu metodu yeni bir oluşum nesnesi oluşturmadan direk çağırırız.
Ama sınıfın bir oluşum nesnesi üzerinden çağıramayız.
-- -- Tekil metodlar
Sınıfın sadece bir tane oluşum nesnesine özel tanımlanan metodlardır (singleton methods). Diğer nesnelerinde çalışmaz.
Tekil ve sınıf metodlarına verilen bir isimlendirme de özsınıflar'dır. Basitçe düşünülürse Ruby bu metodları saklamak için bir anonim sınıf oluşturur ve böylece üretilen nesnelerin oluşum metodları ile karışmazlar.
Bu metodları bir başka tanımlama şekli de class << yapısını kullanmaktır.
-- Dinamik sınıf üretimi
Sınıflar Class.new ifadesi ile dinamik olarak üretilir.
Yukarıdaki örnekte yeni üretilen sınıf BirSınıf sabitine saklanıyor. Bu sınıf önceden gördüğümüz şekilde oluşum nesneleri üretmekte kullanılabilir.
Class.new metodu argümanında başka mevcut bir sınıf adını alarak yeni sınıfı ondan kalıtım yoluyla üretir (mirasçısı yapar).
Class.new metodu argümanında bir blok da alabilir. Bu kod bloğu sınıf tanımının içinde yer almasını istediğiniz kodlardır.
-- new, allocate ve initialize
Ruby'de de diğer bir çok dil gibi sınıf oluşum nesneleri new sınıf metoduyla yapılır. Ama new bir deyim değildir, aslında o da bir sınıf metodudur , diğer sınıf metodlarından bir farkı yoktur. Tanımlaması kabaca şuna benzer.
Esas sihiri sınıfın daha doğmamış nesnesini üreten allocate yapar.
Dikkat edilmesi gereken nokta initialize metodu dönüş değeri kullanılmıyor, direk olarak obj nesnesine etki ediyor.
Tüm sınıf metodlarının Class sınıfından aldığı new metodu yukarıdaki teknikle çalışıyor. Ama isterseniz değiştirebilir ya da farklı çalışan alternatif bir üretici metod tanımlayabilirsiniz.
gibi.
-- Sınıf ve oluşum değişkenleri
Sınıflarda verileri paylaşmak için kullanılan farklı değişken kapsamları vardır. Oluşum değişkenleri @ ile başlar, bunları görmüştük. Bunlar farklı metodlarda aynı değerlere ulaşmak için faydalıdır.
Sınıf değişkenleri @@ ile başlar ve o sınıftan üretilen tüm nesnelerde aynı değeri paylaşır.
Global değişkenler $ ile başlar ve programın her yerinden erişilebilir, bu yüzden dikkatli kullanınız.
Hash veri tipi
Hash sözlük benzeri bir listedir, anahtar kelimeler (key), ve karşılığı değerlerden (value) oluşur. İlişkisel array (associative arrays) dendiği de olur. Yapıları array'e benzer, ancak array'lerde elemanların index değerleri vardır (sıra numaraları) ve onlarla erişilir. Hash index yerine herhangi bir nesne kullanmanıza olanak tanır, bunlara nahtar kelime (key) denir. Yeni bir girdiyi anahtar kullanarak tanımlar ve sonra yine bu anahtar ile erişirsiniz.
Örnekler :
Ruby'de hash'ler bir hash tablosu kullanarak anahtarlar değerlere bağlanır.
Anahtar olarak herhengi bir nesne kullanılabilir ama Ruby'de genel eğilim sembolleri kullanarak hafıza etkinliğini arttırmaktır (string'ler bile bir nesne olarak yer işgal ederken sembollerin sadece değerleri vardır).
gibi.
-- Bir Hash tanımlamak
Ruby'de bir hash hash table uygulaması bir nesnedir, ve anahtarları değerlere eşleştirir. Ruby hash değerleri { } özel yapısıyla tanımlama imkanı sunar.
Bir hash standart new metodu ile de tanımlanabilir.
Hash içinde her türde değer olabilir, hatta karmaşık tipler olan array, nesne ve diğer hash'ler gibi eleman değerleri olabilir.
Anahtarlar da her veri tipinde olabilir.
Hash anahtar kelimesi olarak semboller çok yaygın kullanılır. Ruby 1.9 sonrasında bunları kullanmanın daha kestirme bir yoluna geçildi.
Aşağıdaki hash ise (tüm versiyonlarda geçerlidir) farklı, çünkü anahtar değerleri string. Burada kestirme kullanamazsınız, sadece sembol için geçerli kural.
Bu ikisinden karışım yapılabilir.
Versiyon 2.2 sonrasında çok kelimeden oluşan sembol değerleri için şu notasyon da geçerli oldu.
Bu hash veri tipini Ruby on Rails programcıları çok kullandığı için sürekli basitleştirmeye çalışıyorlar.
-- Default hash değerleri vermek
Default olarak eğer olmayan bir anahtar okunmak istenirse nil değer döner. İsterseniz olmayan bir hash anahtarına ulaşılmaya çalışıldığında dönecek değeri başka bir default değere ayarlayabilirsiniz. Her ne kadar adına default değer dense de isterseniz bir hesaplama sonucunu da (mesela anahtar karakter sayısı) default değer olarak ayarlayabilirsiniz.
Default değer hash üretim metodunda argüman olarak verilir.
Halihazırda tanımlanmış olan bir hash için de default değer verilebilir.
Bu satır başında >> olanlar irb denemeleri oluyor, umarım yanlış anlaşılmıyordur.
Default değer olmayan her anahtara erişilmeye çalışıldığında kopyalanmaz, bu da bize default değerin aslında referans olarak alındığını gösterir.
Burada olmayan değeri bir hesap sonucu belirleyerek sorunu çözebiliriz.
Bu default değer kod bloğunu başka verilere göre bir değer oluşturmak amacıyla da kullanabiliriz.
sadece default değer hesaba göre belirleniyor, önceki koddaki gibi hash içine eleman eklemek yok (hash[key] = [] gibi bir kod yok).
Çok karmaşık hash elemanları da üretebilirsiniz.
Default değer için kod bloğu alındığı gibi Proc nesnesi alabilmek amacıyla default_proc nesne metodu kullanılabilir.
-- Hash eleman değerlerine erişmek
Elemanların değerlerine erişmek ve değiştirmek için daha önceki örneklerde de gördüğümüz gibi [ ] ve [ ]= metodları kullanılır.
Default olarak olmayan bir hash anahtarına erişmeye çalışırsanız nil değer döner, böylece hata oluşmadan güvenli bir şekilde olmayan anahtar sorgulanabilir.
Hash her nesneyi anahtar olarak kabul ettiği için string bir değeri de kabul eder. String yerine sembol gibi erişmeye kalkarsanız nil değer döner.
Eğer ille de anahtar değer bulunsun , yoksa hata oluşsun isterseniz, fetch metodu verilen anahtar yoksa bir hata oluşturur.
fetch metodu ikinci argümanında eğer anahtar bulunamazsa dönülecek default değeri alabilir.
fetch metodu bir blok alarak da bulunamayan anahtarlarda dönecek değeri hesap yoluyla belirleyebilir.
Hash'lerde [ ]= metodu yerine store metodunu da kullanabilirsiniz.
values metodu ile tüm değerleri alabilirsiniz.
Not: bu sadece Ruby 2.3+'da geçerlidir. İç içe hash'lerde dig metodu kullanışlıdır.
-- Otomatik olarak iç içe hash oluşturmak
Önce de görmüştük olmayan anahtarlar için hash default değeri nil'dir.
Default değeri üretici metoda argüman olarak girebiliyorduk.
Default değerin bir hesaplama sonucu olması için bir kod bloğuyla da verebiliyorduk. Lınux shell komutu mkdir -p, veya Perl'ün autovivification davranışı gibi, blok yardımıyla iç içe hash oluşturabiliriz.
:a anahtarı yok - default_proc çalışacak, default_proc ne? zaten verilmiş olan blok - :a nın değeri bir yeni hash olacak. :a'nın içinde :b anahtarı yok ona da aynı işlem yapılıp değeri yeni bir hash olacak. En son :b^nin içindeki :c'ni değeri 3 olacak.
-- Hash elemanlarında iterasyon
Bir Hash içinde birçok yararlı metodlar olan Enumerable modülünü içerir. Bunlardan bazıları: Enumerable#each, Enumerable#each_pair, Enumerable#each_key, ve Enumerable#each_value.
each ve each_pair hash içindeki her anahtar-değer çifti için iterasyon yapar.
each_key sadece anahtarlar üzerinden iterasyon yapar.
each_value sadece değerler üzerinden iterasyon yapar.
each_with_index metodu tüm elemanlar üzerinden iterasyon yaparken size bir de index numarası verir.
Burada (anahtar, değer) ifadesi parantez içindedir, sebebi each_with_index metodu elemanı ve index değerini döner, ama bir hash nesnesine uygulanınca eleman olarak bir anahtar-değer çifti dönecektir. Şöyle de yazılabilir:
-- Array - Hash dönüşümleri
Hash array'e , array de hash'e dönüştürülebilir. Bir hash değeri anahtar-değer çiftleri içeren alt array'ler şeklinde dönüştürmek için to_a metodu kullanılır.
Tersi yönde bir hash de bu düzende yazılmış bir array'den to_h metodu ile dönüşütürülebillir.
Benzer bir şekilde yeni hash tanımlarken Hash[ ] ifadesi kullanarak sıralı anahar-değer dizisi ile tanımlanabilir.
Hash değerler sıralı anahtar-değer elemanları içeren array'e flatten metodu ile dönüştürülür.
İç içe array'den hash'e dönüştürme yapısı Enumerable modülünün metodları yardımıyla daha etkili kullanılabilir.
-- Hash elemanlarını filtrelemek
select metodu arkasından verilen kod bloğunun true değer döndüğü elemanları içeren yeni bir hash üretir.
Eğer filtreleme bloğu içerisinde anahtar ya da değerden birini kullanmayacaksanız, kod temizliği açısından yerine ( _ ) koyabilirsiniz.
reject metodu ise bloğun false değer döndüğü çiftlerden yeni bir hash oluşturur.
Böylece aynı satırı bir select, bir reject ile kullanarak hash değeri filtreye uyanlar ve uymayanlar olarak ikiye parçalayabilirsiniz.
-- Tüm anahtar ya da değerleri bulmak
-- hash metodunun üstüne yazmak
Ruby hash değerlerde elemanlara atama yaparken aynı nesnelere sahip anahtarlara aynı değerleri vermek için hash ve eql? metodlarını kullanır. Bu metodların üstüne yazarak istediğimiz davranışı belirleyebiliriz.
Bir örnek verelim
Fakat diyelim biz her iki nesneye de aynı @hash_value değerini girdiğimiz için hash içinde aynı elemanlara erişmesini istiyoruz, veride ikileme olmasın istiyoruz. Bu durumda sınıf tanımında hash metodu ve Ruby'nin karşılaştırırken kullandığı eql? üzerine yazarız.
a nesnesi daha önce tanımlandığı için onu aldı ve b anahtarı kullanarak yazılan değeri de aynı kutuya yazdı (çünkü ikisini eşit görüyor).
-- Hash elemanlarında anahtar ve değerleri değiştirmek
Yeni bir hash tanımlarken anahtar ve değerleri vermesini gördük, sonradan anahtarlara değer atamasını gördük, sonradan nahtarı değiştirme ya da silme işi için de inject (diğer adıyla reduce) metodu kullanılır. Örneğin hash elemanlarının anahtarlarını string'e dönüştürmek ve değerlerini büyük harf yapmak için bir kod yazalım.
Hash bir enumerable'dır ve özünde anahtar-değer çiftlerinden oluşur. Bu yüzden each, map ve inject gibi metodları vardır.
Hash içindeki her anahtar-değer veri çifti için inject arkasından verilen bloktaki kod çalıştırılır. İlk turda memo değişkeni inject metodunun argümanı nesneyi içerir, burada boş bir hash nesnesi. Bloğa geçen ikici değer ise kolleksiyondaki eleman, eğer bu bir array olsa ya da bir range, orada o turda işlenecek eleman değeri olacaktı, bu bir hash olduğu için bir anahtar-değer çifti gelecektir, onu da parantez içinde k (key) ve v (value) şeklinde ikiye ayırdık.
meyve hash verisindeki ilk eleman ( :isim=>"elma" ) çifti, bu eleman kod bloğu içinde işlenince memo akümülatör değişkeninin ilk elemanı oluşuyor ( "isim"=>"ELMA" ). Kalınan yerden eklemeye sonraki iterasyonlarda devam edilsin diye memo değişkenini bloktan dönen değer yapıyoruz, çünkü ilk turdan sonraki turlarda kod bloğundan dönen değer sonraki turda memo akümületör değeri olarak kullanılacak. Tabi bunu inject metodu yapacak , zaten bizden argümanla aynı tipte değer bekleyecektir, kendisine bloktan bir hash dönmek zorundayız. Dönmesek ne olur?
sınuçta koddan dönen değer string (mesela "ELMA" gibi), ve bir sonraki turda bu dönen değer hash olmadığı için hata oluşturacak. Neler olduğunu görmek için kod ekleyelim.
Görüjdüğü üzere ilk turda memo={} - ikinci turda ise ilk turun dönen değeri olan "ELMA". Tabii memo="ELMA" olunca ikinci turda oluşturulacak memo["renk"] ifadesi bir hata oluşturuyor (İşin kötüsü .string değer "renk" içerse hata vermezdi).
Her seferinde son ulaşılan değeri kod bloğundan dönmek yerine each_with_object metodu da kullanılabilir.
Bu da aynı işi yapar, ama burada önce eleman sonra nesne veriliyor argümanda, dikkat ediniz.
Ya da map metodu kullanırız.
-- Hash'ler arası işlemler
-- -- Hash'lerin kesişimi bulunması
Hash'lerin anahtar-değer çiftlerinde eşit olanları kesişimi oluşturur.
-- -- Hash'lerin bileşimi bulunması
Hash içinde anahtar değerleri tek olur, birleştirilen hash'lerde merge metodunun uygulandığı hash nesnesindeki anahtarın üstüne yazılır.
Blok'lar Proc'lar ve Lambda'lar
-- Blok deyimleri
-- Bloklarda dikkat edilmesi gerekenler
Birçok metodu zincirleme bağlarken operatör önceliklerine dikkat ediniz.
Bu kodun abCDeFg gibi bir çıktı vermesini beklerken bir enumerator nesnesi verdi. Sebebi do...end ifadesinin önceliğinin metodlardan düşük olması , puts metodu sadece puts str.gsub(/./) olarak çalıştı, do bloğunun arkadan geldiğini gsub algılayamadı.
Bunun üstesinden gelmek için ya bloğu { } içinde yazarız,
ya da gsub metodunu komple parantez içine alırız.
gibi.
-- Lambda'lar
Lambda'lar bir kod bloğunu parametreleri ile tanımlamaya yarayan nesnelerdir, ve bir değişkene konabilirler.
Lambda ve Proc birbirine benziyor ama farkları var:
- Lambda argümanları zorunludur, bir lambda'ya yanlış sayıda argüman girmek ArgumentError hatası verir. Ama default değerler vs kullanılabilir.
- Bir lambda'dan dönüşte sadece lambda'dan dönülür ama bir proc'dan dönüşte onu kapsayan bloktan da çıkılır.
-- curry metodu ve parça kullanma
Bu metod/fonksiyon parametre olarak n değerini alır, ikiye katlar ve değeri döner. Haydi daha gelişmiş bir metod yazalım.
triple metodu bize değer dönmek yerine bir lambda kod bloğu dönüyor. IRB oturumunda deneyelim.
Gerçekten 3'e katlanmış bir sayı istiyorsak metoddan dönen lambda'yı çalıştırmalıyız.
ya da kısacası
-- -- curry metodu ile parçalı çalışmak
Yukarıda anlattıklarımız basit işler yaparken pek yararlı görünmüyor. Ama benzer işi yapan birçok metod tanımlarken çok işimize yarar. Diyelim verdiğimiz sayıya bir, iki ve üç ekleyen metodlar tanımlayacağız.
Bir sürü benzer metod tanımlaması yerine, curry metodu kullanabiliriz.
Lambda hesaplamasına göre ekle lambda ifadesi (λa.(λb.(a+b))) olarak gösterilir. curry ile ekle lambda'sına parçasal erişim tanımlıyoruz. Bu durumda ekle.curry.(1) karşılığı (λa.(λb.(a+b)))(1) olur, yani (λb.(1+b)) olur. Böylece ekle bloğuna gidecek ilk argümanı vermiş ikincisini kullanımına bırakmış oluruz.
-- -- Başka curry örnekleri
Diyelim çok büyük genel bir formülümüz var ve bazı değerleri sabit girerek azaltılmış özel formüller üretebileceğimizi düşünüyoruz.
Bu formül üç boyutta çalışıyor. Fakat diyelim biz bu formülün sadece x=PI/2 olduğu y-z iki boyutlu düzlemindeki formülünü bulmak istiyoruz. Öncelikle Ruby diline uygun formülümüzü oluşturalım.
Şimdi y-z düzlemindeki özel formülümüzü üretelim.
Sonra da yeni formülü deneyelim.
İlk parametre olan x'i dışarda bırakmayı gördük. Peki ikinci parametreyi dışarda bırakıp f_xz özel formülüne ulaşmak istersek? Evet, orası biraz daha karışık.
Benzer şekilde z değerinin sabit olduğu formüle de erişebiliriz.
gibi.
-- Metodlara nesneleri blok argüman olarak vermek
Bir metoda argüman girerken önüne & ekleyince , argüman eğer bir metodsa kod bloğu, bir nesneyse onun to_proc metodunun dönen değeri (bir Proc nesnesi) argümana verilir.
Bu Ruby'de genel bir şablondur ve birçok standart sınıfta bulunur.
Örneğin Symbol sınıfının to_proc uyarlaması argümana kendisini göndermesi şeklindedir.
basitleştirilmiş yapısı buna benzer. Yani bir nesneye & ile bir sembol argüman verildiğinde o nesnede sembol ile belirtilen metod çağrılır. Bildiğimiz üzere send metodu o nesnede metod çağırır.
gibi.
Bu &:sembol yapısı Enumerable nesnelerde çok faydalıdır.
-- Proc nesnesine çevirmek
to_proc'a yanıt veren nesneler (yani to_proc metodu tanımlı olan nesneler) & operatörüyle proc'lara dönüştürülebilir (böylece argümana blok olarak verilebilirler).
Symbol sınıfında to_proc tanımlıdır, bu sayede parametresinde verildiği nesne üzerinde karşılık gelen metodu çalıştırır.
Bu aslında
kodunun eşleniği. Sembol değer map metodundan gönderilen x nesnesini alıp onun upcase metodunu otomatik olarak çağırıyor.
Metod nesnelerinde de (Ruby'de herşey bir nesnedir) to_proc tanımlıdır.
-- Kod blokları
Kod bloklarının tek satır için { } arasında , çok satır için do...end bloğu içinde gösterilmesi tavsiye edilir.
Not: Süslü parantezlerin do...end bloklarından öncelikli çalıştırıldığını unutmayınız.
-- -- yield ile blok kodunu çalıştırmak
Bloglar argümanında verildikleri metodların içinde yield ifadesi ile kullanılırlar.
Dikkat edilmesi gereken konu, argümanda blok verilmeden yield çağrılırsa hata verir.
Eğer blok verilmese de metodumuzun hata vermeden devam etmesini istersek block_given? metodunu kullanabiliriz.
yield ifadesi bağlı bloğa argüman da gönderebilir.
Bu basit bir örnek gibi görünse de yield ile oluşum değişkenleri ve diğer nesnelerin içindeki hesaplamalara erişmeleri sayesinde etkili kullanılabilir.
Burada görüldüğü gibi yaparsak Yapılandırma sınıfından üretilen @yapılandırma nesnesi üzerinde sürekli app.yapılandırma#metod_adı gibi metodlar çağıracağımıza yield'e vereceğimiz blok içinde birçok şeyi yapabiliriz.
-- -- Blok içindeki değişkenler
Blok içinde tanımlanan değişkenler bloğa yerel olarak kaydedilir ve bloktan çıkılınca yok edilir (metod içleri gibi).
Blok dışında tanımlanan değişkene blok içinden erişilebilir.
Bu olayda bir sıradışı davranış var, blok parametresine dış değişken ile aynı isim verilmesi.
Bloklar bir yere saklanamazlar, çalıştırılırlar ve yok olurlar. Blokları saklamak için Proc yada Lambda kullanılır.
-- Proc nesnesi
Örnekler:
Görüldüğü gibi blok_çağır metoduna çağrılacak olan bloğu & ile ifade ediyoruz. Bu hem metoda bir argüman değil bir blok beklentisini bildiriyor, hem de gelen bloğu bir Proc nesnesine dönüştürüyor. blok_çağır metodunu arkasında blok olmadan çağırırsak hata verir ama bloğu vermediğimiz yerde değil metod tanımı yapılan 2. satırda verir, bu yüzden avlaması zor olacaktır.
bu_bir Proc nesnesinin tanımından gördüğünüz gibi metodlar gibi yıldızlı parametre kabul ediyor. Değişik çağrılarla deneme yapalım.
Kalıtım'la devam edeceğiz inşallah. Şimdilik kalın sağlıcakla..
Hiç yorum yok:
Yorum Gönder