5 Değişkenler Her dilde olduğu gibi, Ruby’de de veriler değişkenlere ve sabitlere atanır. Bazı dillerde olduğu gibi, Ruby’de değişkenin veri tipi, değişken bildiriminde belirlenmez. Atanan değere bakarak, Ruby, değişkenin veri tipini kendisi belirler. Gene de, alışkanlığı korumak için, yapılan eyleme değişken bildirimi diyeceğiz. Bildirimi yapılan her değişken kendisine atanan verinin ana bellekte bulunduğu adresi gösteren işaretçidir (referans, pointer). Değişkenin değeri işaret ettiği yerde konuşlanan değerdir. 5.1 Atama Atama işlemi bir değişkene bir nesnenin ya da bir ifadenin verilmesi eylemidir. Örneğin, x = 1 bir atama işlemidir. Bu deyimde x değişken, 1 ise ona atanan nesnedir. Aradaki eşit (=) simgesi atama eylemini gerçekleştiren operatördür. Eşit (=) operatörü baskılanamaz (override edilemez). Değişken daima eşit simgesinin solunda olur. Eşit simgesinin sağına bir nesne ya da ifade konulur. Değişken, kendisine atanan nesnenin ana bellekteki adresini gösteren işaretçidir. Buna referans ya da pointer adları da verilir. Atamalar Liste 5.1 ile gösterilen türlerden olabilir. Burada ifade bir ya da birden çok Ruby deyiminin ard arda işlenmesiyle elde edilen nesne anlamındadır. Örneğin, 3 ∗ 5/2 − 17 bir aritmetik ifadedir, "Ankara" + "başkenttir" ise bir string ifadesidir. BÖLÜM 5. DEĞIŞKENLER 52 Liste 5.1. 2 değişken = ifade constant = değer değişken = nesne Örnekler: Liste 5.2 ’de 1.satır 17 ∗ 3/2 ifadesini x değişkenine atıyor. x’in değeri 25 olur. 2.satır personel adlı arrayin üçüncü bileşenine "Can" değerini atıyor. 3.satır Bitki adlı sınıfın ad değişkenine "Marul" değerini atıyor. Liste 5.2. 2 x = 17∗3/2 p e r s o n e l [ 2 ] = " Can " B i t k i . ad = " Marul " Paralel Atamalar Çoklu atamalar bir arada yapılabilir. Bu eyleme paralel atama da denilir Liste 5.3. 2 7 x,y,z = 1, 2, 3 x = y; y = x x,y = y.x # x = 1, y = 2, z = 3 # x i l e y aynı d e ğ e r i a l ı r # t a k a s ( swap ) ; x i l e y n i n d e ğ e r l e r i y e r d e ğ i ş i r x , y = [1 , 2] x, y = 1, 2 x, y = 1 # x = 1; y = 2 # x = 1; y = 2 # x = 1; y = nil x, y, z = 1, 2 x, y = 1, 2, 3 x ,∗y = 1 , 2 , 3 # x = 1; y = 2; z = nil # x = 1; y = 2 # x = 1; y = [2 , 3] Birleşik Atamalar Sayısal atamalarda, bazen eşit yerine + =, − =, ∗ =, / =, % = . . . simgeleri konulabilir (bkz. Bölüm 6). Örneğin, x +=1 y −=1 # => x = x + 1 # => y = y − 1 5.1. ATAMA 5.1.1 53 Metot Çağırma Ruby’de metot çağırma eylemi, alıcıya bir ileti (mesaj) gönderme eylemidir. obj nesnesindeki m metodunu çağırmak için obj.m yazarız. Bu deyim obj nesnesine m metodunu çalıştırmasını söyler. Gerçekten varsa, m metodu çalışır. Yoksa hata verir. m metodunun içinde varsaa self anahtar sözcüğü (değişkenimsi, pseudo variable) obj nesnesini işaret eder. Bir obj nesnesine uygulanabilen m metodunu m(1) nesnesi için çağırmak istersek aşağıdaki deyimlerden birisini kullanabiliriz. İlk deyimde (=) simgesinin sağında ve solunda boşluk olmadığına dikkat ediniz. m simgesinin metot olduğunu belirtmek için daima sağına eşit simgesi konulur; yani m= biçiminde yazılır. o b j .m=(1) o b j .m = 1 Bazen obj.m değişken (sol-değer, lvalue) olarak kullanılabilir. Bu değişkene bir d değerini atamak için obj.m= d deyimi kullanılabilir. Ruby derleyicisi bu deyimi obj.m=(v) olarak yorumlar. Ama () parantezi yazılmaz ya da eşit simgesinden sonra boşluk konulursa, Ruby onu fonksiyon olarak değil, bir atama işlemi olarak algılar. Çoklu Atamalar Bir tane sol-değere karşılık birden çok sağ değer olduğunda, Ruby o atamayı bir array olarak algılar: x = 1 , 2 , 3 # => x = [ 1 , 2 , 3 ] Çoklu sağ-değerlerden bir array oluşturulması istenmiyorsa, sol-değerden sonra (,) konulur. x, = 1, 2, 3 # => x = 1 o l u r , ö t e k i l e r ihmal e d i l i r . Sol-değer çoklu, sağ-değer tekli ise, aşağıdaki gibi yazılır: z ,y , z = [1 ,2 ,3] # => x , y , z = 1 , 2 , 3 BÖLÜM 5. DEĞIŞKENLER 54 5.2 Ruby’de Değişken Türleri Ruby’de beş türlü değişken vardır: 1. Global değişkenler 2. Sınıf değişkenleri 3. Anlık (instance) değişkenler 4. Yerel değişkenler 5. Değişkenimsiler (pseudo variables) Yerel değişken dışındakiler öntakıları ile belirlenir. Sigil denilen öntakılar değişkenin geçerlilik bölgesini (variable scope) belirler. Öntakılar $, @, @@ simgeleridir. 5.3 Global Değişkenler Liste 5.4. > $x #=> nil > $x = #=> 7 > $x #=> 7 Global değişken, bütün programın her yerinden erişilebilecek değişkendir. Global değişken adları $ simgesiyle başlar. Değer atanmamış değişkenlerin öntanımlı değeri nil’dir. Değer atanmamış değişkenler programda kullanılırsa, derleyici uyarı yollar. Liste 5.5, global değişkenin programda kullanılışını gösteriyor. Liste 5.5. #e n c o d i n g UTF−8 4 9 $ s a y ı = 10 c l a s s Class1 def print_global p u t s " C l a s s 1 i ç i n d e k i G l o b a l d e ğ i ş k e n : #$ s a y ı " end end c l a s s Class2 def print_global p u t s " " C l a s s 2 i ç i n d e k i G l o b a l d e ğ i ş k e n : #$ s a y ı " 5.3. GLOBAL DEĞIŞKENLER 55 end end 14 class1obj class1obj class2obj class2obj 2 = C l a s s 1 . new . print_global = C l a s s 2 . new . print_global /∗ ∗ C l a s s 1 i ç i n d e k i G l o b a l d e ğ i ş k e n : 10 C l a s s 2 i ç i n d e k i G l o b a l d e ğ i ş k e n : 10 ∗/ Açıklamalar: Burada $sayı global bir değişkendir. Programın çıktısından görüldüğü gibi, global değişkenin değeri sınıfa göre değişmiyor. Uyarı: Global değişkenin değeri program içinde her yerden değiştirilebilir. Bu iş bilinçli yapılmazsa, programın kalan kısmında beklenmedik sonuçlar çıkabilir. Program 5.1. 1 6 11 # e n c o d i n g UTF−8 $ h ı z _ l i m i t i = 82 def hızlan $ h ı z _ l i m i t i = 90 end ... def radar i f $ h ı z _ l i m i t i > 82 p u t s " Hız l i m i t i n i end end aştınız . Cezalısınız ! " hızlan radar Açıklamalar: 3.satırda $hız_limiti adlı global değişkenin değeri 82 olarak belirlendi. Diyelim ki, programcı bütün program boyunca bu değeri kullanmak istiyor. Ama uzun bir programda, farkında olmadan hızlan metodu ile 5.satırdaki atama $hız_limiti’nin değerini değiştiriyor. Bu değişikliğin olduğu yerden sonraki kısımlarda, $hız_limiti’nin değeri 82 değil, 90 olarak gelecektir. Programcı bu değişikliği bilinçli yapmamışsa; yani global değişkenin değerini değiştirdiğinin farkında değilse, programın geri kalan kısmında global değişkene bağlı sonuçlar yanlış çıkacaktır. Bazen bu yanlışın farkına varılmayabilir. Farkına avarıldığı durumlarda da, uzun programlarda değişikliğin yapıldığı yeri bulmak zor olabilir. O nedenle, büyük programlarda BÖLÜM 5. DEĞIŞKENLER 56 global değişkenler çok dikkatle kullanılmalıdır. Bazı programcılar global değişkenin hiç kullanılmamasını önerirler. Program 5.2. #! / u s r / b i n / ruby $gb = 6 5 module ModuleM p u t s " module i ç i n d e " p u t s $gb end 10 15 20 d e f method1 p u t s " method i ç i n d e " p u t s $gb end c l a s s Some puts " c l a s s i ç i n d e " p u t s $gb end method1 25 p u t s " Üst kapsanma a l a n ı n d a " p u t s $gb p u t s g l o b a l _ v a r i a b l e s . i n c l u d e ? : $gb 5.4 Sınıf Değişkenleri Sınıf değişkenleri, değişkenin tanımlandığı sınıfta ve onun bütün altsınıflarında (oğul) ve modüllerinde geçerlidir. Sınıf değişkenleri @@ ile başlar. Sınıf değişkenlerine kullanılmadan önce değer verilmelidir. Değer atanmamış sınıf değişkeni çağrıldığında derleyici hata olduğu uyarısı yapar. Sınıf değişkenlerinin bildirimini yapmak kolaydır. Sınıfı tanımlayınız, değişkenin önüne @@ simgelerini koyunuz ve değerini atayınız. Program 5.3. 3 c l a s s Poligon @@kenar_sayısı = 12 def s e l f . kenar_sayısı @@kenar_sayısı end end 5.5. ANLIK DEĞIŞKENLER 8 57 p u t s P o l i g o n . k e n a r _ s a y ı s ı # => 12 Sınıf değişkenleri baskılandığında (overriding) uyarı verilir. Program 5.4, sınıf değişkeninin kullanılışını gösteriyor. Program 5.4. # e n c o d i n g UTF−8 2 7 12 17 22 27 2 c l a s s Müşteri @ @ m ü ş t e r i _ s a y ı s ı=0 d e f b a ş l a t ( no , ad , addr ) @müşteri_no=no @müşteri_adı=ad @ m ü ş t e r i _ a d r e s i=addr end def display_details () p u t s " M ü ş t e r i No #@müşteri_no " p u t s " M ü ş t e r i Adı #@müşteri_adı " p u t s " M ü ş t e r i A d r e s i : #@ m ü ş t e r i _ a d r e s i " end def toplam_müşteri_sayısı () @ @ m ü ş t e r i _ s a y ı s ı += 1 p u t s " Toplam M ü ş t e r i S a y ı s ı : #@ @ m ü ş t e r i _ s a y ı s ı " end end # Nesneleri yarat m ü ş t e r i 1=M ü ş t e r i . new m ü ş t e r i 1 . b a ş l a t ( " 1 " , " M e l i k e " , "GMK 1 4 / 3 , Ankara " ) m ü ş t e r i 2=M ü ş t e r i . new m ü ş t e r i 2 . b a ş l a t ( " 2 " , " A n ı l " , " İ s t i k l a l Caddesi 3 7 / 8 , İ s t a n b u l " ) # Çağrılar müşteri1 . toplam_müşteri_sayısı () müşteri2 . toplam_müşteri_sayısı () /∗ ∗ Çıktı : Toplam M ü ş t e r i S a y ı s ı : 1 Toplam M ü ş t e r i S a y ı s ı : 2 ∗/ 5.5 Anlık Değişkenler Anlık değişken (instance variable) yalnızca üretilen nesne (instance) içinde geçerlidir. Ruby’de anlık değişkenlerin önüne @ simgesi konulur. Değer atanmamış anlık değişkenlerin öntanımlı değeri nil’dir. Değer atanmamış değişkenler programda kullanılırsa, derleyici uyarı yollar. BÖLÜM 5. DEĞIŞKENLER 58 Program 5.5 içindeki anlık değişkenler şunlardır: @müşteri_no, @müşteri_adı and müşteri_adresi. Program 5.5. #e n c o d i n g UTF−8 5 10 c l a s s Müşteri d e f b a ş l a t ( no , ad , addr ) @müşteri_no=no @müşteri_adı=ad @ m ü ş t e r i _ a d r e s i=addr end def göster () p u t s " M ü ş t e r i No : #@müşteri_no " p u t s " M ü ş t e r i Adı : #@müşteri_adı " p u t s " M ü ş t e r i A d r e s i : #@ m ü ş t e r i _ a d r e s i " end end 15 20 # Nesneleri yarat m ü ş t e r i 1=M ü ş t e r i . new m ü ş t e r i 1 . b a ş l a t ( " 1 " , " M e l i k e " , "GMK 1 4 / 3 , Ankara " ) m ü ş t e r i 2=M ü ş t e r i . new m ü ş t e r i 2 . b a ş l a t ( " 2 " , " A n ı l " , " İ s t i k l a l Caddesi 3 7 / 8 , İ s t a n b u l " ) # Çağrılar müşteri1 . göster () müşteri2 . göster 1 6 /∗ ∗ Müşteri Müşteri Müşteri Müşteri Müşteri Müşteri ∗/ No : 1 Adı : M e l i k e A d r e s i : GMK 1 4 / 3 , Ankara No : 2 Adı : A n ı l A d r e s i : İ s t i k l a l Caddesi 3 7 / 8 , İ s t a n b u l self anahtar sözcüğü, önüne geldiği öğeyi o anda etkin olan nesneye ait yapar. Program 5.6. 2 7 # e n c o d i n g UTF−8 c l a s s Ceviz @ceviz_sayısı = 0 def s e l f . sayaç @ c e v i z _ s a y ı s ı += 1 end def s e l f . şimdiki_sayı @ceviz_sayısı 5.5. ANLIK DEĞIŞKENLER 12 59 end end c l a s s Fındık < Ceviz @ c e v i z _ s a y ı s ı = 15 end 17 Ceviz . sayaç Fındık . sayaç p Ceviz . şimdiki_sayı p Fındık . şimdiki_sayı 4 /∗ ∗ 1 16 ∗/ Uyarı: 3.satırdaki anlık @ceviz_sayısı değişkenine değer atanmazsa programda onu kullanan metotların hepsi için undefined method ’. . . ’ for nil:NilClass hata uyarısı gelir. Bu uyarı, değer atanmamış değişkenin nil olduğu ve onunla işlem yapılamadığını söylüyor. Program 5.7 sınıf ve anlık değişkenlerin kullanılışını gösteriyor. Program 5.7. 1 6 11 #e n c o d i n g UTF−8 c l a s s Ebeveyn @varlık = [ ] def s e l f . varlık @varlık end def varlık se l f . class . varlık end end c l a s s Cocuk < Ebeveyn @varlık = [ ] end 16 Ebeveyn . v a r l ı k << : o t o m o b i l Cocuk . v a r l ı k << : e v l a t anne = Ebeveyn . new baba = Ebeveyn . new 21 p p p p Ebeveyn . v a r l ı k #=> [ : o t o m o b i l ] Cocuk . v a r l ı k #=> [ : e v l a t ] anne . v a r l ı k #=> [ : o t o m o b i l ] baba . v a r l ı k #=> [ : o t o m o b i l ] 26 # Sınıf değişkenleri : BÖLÜM 5. DEĞIŞKENLER 60 31 36 c l a s s Ebeveyn @@varlık = [ ] def s e l f . varlık @@varlık end def varlık @@varlık end end c l a s s Cocuk < Ebeveyn end 41 Ebeveyn . v a r l ı k << : o t o m o b i l Cocuk . v a r l ı k << : e v l a t 46 51 3 8 p Ebeveyn . v a r l ı k #=> [ : o t o m o b i l , : e v l a t ] p Cocuk . v a r l ı k #=> [ : o t o m o b i l , : e v l a t ] anne = Ebeveyn . new baba = Ebeveyn . new o ğ l a n 1 = Cocuk . new o ğ l a n 2 = Cocuk . new k ı z = Cocuk . new /∗ ∗ [: [: [: [: [: [: ∗/ otomobil ] evlat ] otomobil ] otomobil ] otomobil , : e v l a t ] otomobil , : e v l a t ] 5.5.1 Verici (setter) Metotlar Program 5.8, bir sınıfta tanımlanan anlık değişkenlere verici (setter) metoduyla nasıl değer atandığını gösteriyor. Burada cins_ver, yazar_ver ve tarih_ver metotları verici (setter) metotlardır; yani değişkenlere değer atarlar. 19 - 21. satırlar, anlık değişkenlere atanan değerleri yazıyor. 23 - 25.satırlar nil değer veriyor. Bunun anlamı, nesne içindeki verici metotlarla anlık değişkenlere atanan değerlere dışarıdan erişilemediğidir. Program 5.8. #e n c o d i n g UTF−8 2 c l a s s EsereVer def cins_ver ( tip ) @name = t i p end 5.5. ANLIK DEĞIŞKENLER 61 7 d e f yazar_ver ( i s i m ) @ad = i s i m end 12 def tarih_ver ( y ı l ) @tarih = y ı l end end 17 e = E s e r e V e r . new p e . c i n s _ v e r ( " roman " ) p e . yazar_ver ( " Orhan Kemal " ) p e . tarih_ver (1957) 22 p @name p @ad p @tarih 5 /∗ ∗ " roman " " Orhan Kemal " 1957 nil nil nil ∗/ 5.5.2 Alıcı (getter) Metotlar Program 5.9, bir sınıfta tanımlanan anlık değişkenlere verici (setter) metotlarıyla atanan değerlere, nesne içindeki alıcı (getter) metotlarıyla nasıl erişildiğini gösteriyor. Burada cins_al, yazar_al ve tarih_al metotları alıcı (getter) metotlardır. Verici ve alıcı metotlara istenen adlar verilebilir. Program 5.9’de, algılamayı kolaylaştırmak için _ver ile _al sonekleri kullanıldı. p metodu print yerine geçer Program 5.9. #e n c o d i n g UTF−8 2 c l a s s EsereVer def cins_ver ( tip ) @name = t i p end 7 d e f yazar_ver ( i s i m ) @ad = i s i m end 12 def tarih_ver ( y ı l ) BÖLÜM 5. DEĞIŞKENLER 62 @tarih = y ı l end 17 22 27 def cins_al @name end d e f yazar_al @ad end def tarih_al @tarih end end e = E s e r e V e r . new 32 37 2 e . c i n s _ v e r ( " roman " ) e . yazar_ver ( " Orhan Kemal " ) e . tarih_ver (1957) p e . cins_al p e . yazar_al p e . tarih_al /∗ ∗ " roman " " Orhan Kemal " 1957 ∗/ 5.5.3 initialize metodu Kesim 3.9!de initialize metodundan söz etmiştik. Nesne tabanlı programlama dillerinde bir sınıftan nesne üretmek (instantiate) için kurucu (constructor) metotları kullanılır. Ruby bu eylemi initialize metodu ile yapar. Bunu nasıl yaptığını bir örnek üzerinde gösterelim (bkz. [3]). Program 5.10. #e n c o d i n g UTF−8 5 c l a s s Nokta def i n i t i a l i z e (x , y) @x , @y = x , y end end new metodu ile Nokta sınıfından bir nesne üretilince, initialize metodu nesne içinde kendiliğinden çalışmaya başlar. new metoduna verilen argümanlar 5.5. ANLIK DEĞIŞKENLER 63 initialize metoduna geçer. O da kendisine gelen değerleri anlık değişkenlere aktarır. Örneğin, Nokta sınıfından bir nesne üretmek için nokta = Nokta.new (0,0) deyimi kullanılır. Bu deyim Nokta sınıfından nokta adlı bir nesne üretir ve x = 0, y = 0 atamalarını yapar. initialize metodunun tanımına bakarsak, bu değerlerin hemen @x, @y anlık değişkenlerine aktarıldığını görürüz. Böylece sınıfın anlık değişkenlerine, nesne yaratılırken new metoduna atanan argümanlarla değer verilmiş oluyor. initialize metodunun erişim belirteci private ’dir. nokta nesnesi onu çağırabilir, ama ona dışarıdan yeni argümanlar atanamaz. Nokta sınıfından üretilen her nesne için söylediklerimiz geçerlidir. Örneğin, a = Nokta.new(3,2) deyimi, a adlı başka bir esne yaratacak ve o nesne içindeki anlık değişkenlere @x=3, @y=2 ataması yapılmış olacaktır. Aşağıdaki program initialze metodunun kullanılışını gösteriyor. Program 5.11. #e n c o d i n g UTF−8 3 8 13 c l a s s Gezegenler @@gezegen_ say ısı = 0 d e f i n i t i a l i z e ( ad ) @name = ad @@gezegen_ say ısı += 1 end def s e l f . gezegen_sayısı @@gezegen_ say ısı end end G e z e g e n l e r . new ( " e a r t h " ) ; G e z e g e n l e r . new ( " uranus " ) 18 p Gezegenler . gezegen_sayısı 1 /∗ ∗ 2 ∗/ 5.5.4 Kapsülleme Bir sınıfın anlık (instance) değişkenlerine ancak sınıftan türetilen nesne içinden erişilebilir. Nesne dışındaki kodlar, nesne içindeki değişkenlere erişemez. BÖLÜM 5. DEĞIŞKENLER 64 Bu özelik, nesne tabanlı programlamanın kapsülleme (encapsulation) denilen önemli bir özeliğidir. Anlık değişken değerlerine ancak verici ve alıcı metotlarla ulaşılabiliyor oluşu, anlık değişken değerlerine güvenlik sağlar. Sınıfın değişkenlerine dışarıdan erişilmesini engellediği için, kapsülleme çoğunlukla tercih edilir. Program 5.12. #e n c o d i n g UTF−8 2 c l a s s Nokta def i n i t i a l i z e (x , y) @x , @y = x , y end 7 def xal @x end # x için a l ı c ı ( g e t t e r ) metodu 12 def yal @y end end # y için a l ı c ı ( g e t t e r ) metodu 17 p a = Nokta . new ( 2 , 3 ) p b = Nokta . new ( a . x a l ∗ 2 , a . y a l ∗ 3 ) puts a puts b Programın çıktısı şudur: 4 #<Nokta : 0 x2618820 @x=2 , @y=3> #<Nokta : 0 x26183e8 @x=4 , @y=9> #<Nokta : 0 x2618820> #<Nokta : 0 x26183e8> Açıklamalar: 17.satır Nokta sınıfından a adlı nesneyi, 18.satır Nokta sınıfından b adlı nesneyi üretiyor. Bu iki nesnenin farklı olduklarını 20. ve 21. stırların çıktılarından görebiliriz. Çıktıdaki hex tipinden sayılar, Ruby’nin nesnelere verdiği numaralardır. Bir anlamda a ile b pointerlerinin işaret ettikleri bellek adresleridir. 17. ve 18. satırda p metodu, new operatörünün yaptığı işi yazıyor; nesnelerin adresleri ile birlikte @x, @y koordinatlarına atanan değerleri gösteriyor. 18.satır, b nesnesi içinden a nesnesindeki xal ve yal metotlarını çağırıyor. Bu eyleme, nesne tabanlı dillerde ulak yollama (mesajlaşma) denilir. Bu yöntem ile bir nesne içinden başka bir nesne içindeki metot çağırılıp çalıştırabilir. 5.5. ANLIK DEĞIŞKENLER 5.5.5 65 Nitelem (attribute) Metotları Anlık değişkenlere alıcı ve verici metotlarla nasıl erişildiğini biliyoruz. Onlara ek olarak, Ruby, anlık değişkenlere erişimi kolaylaştıran başka metotlara sahiptir. Bazı kaynaklar, attribute metotlarına değişken der. Onlara ne dendiğinden çok, ne yaptıklarını bilmemiz gerekiyor. Nitelem (attribute) metotları denilen bu metotlar, verici ve alıcı metotların yaptığı işleri daha kısa kodlarla yapar. Ruby verici olarak attr_writer, alıcı olarak attr_reader ve her ikisini yapan attr_accessor metotlarına sahiptir. Sonuncuyu tek ve çok değişkenler için ikiye ayırırsak, Tablo 5.1 ile verilen listeyi yapabiliriz. Tablo 5.1: attr Metotları Kısaltma attr_reader :v attr_writer :v attr_accessor :v attr_accessor :v, :w Metot Tanımı def v; @v; end def v=(value); @v=value; end attr_reader :v; attr_writer :v attr_accessor :v; attr_accessor :w Nitelem metotları tanımlarken aşağıdaki ifadeleri kullanabiliriz: Liste 5.6, @x ile @y anlık değişkenlerine verici ve alıcı metotlarını tanımlıyor. Liste 5.6. 1 c l a s s Nokta attr_accessor end :x, :y Liste 5.7, @x ile @y anlık değişkenlerine alıcı metot tanımlıyor. Yalnız alıcı metodu olan anlık değişkenler değiştirilemez (immutable). Liste 5.7. 2 c l a s s Nokta attr_reader end :x, :y Liste 5.7 yerine aşağıdaki ifade de kullanılabilir. attr_reader "x" , "y" Liste 5.8 ifadesi @x anlık değişkenine alıcı metot tanımlıyor. Liste 5.8. BÖLÜM 5. DEĞIŞKENLER 66 attr :x Liste 5.9 ifadesi @x anlık değişkenine verici ve alıcı metotlar tanımlıyor. Liste 5.9. attr :y , true Açıklamalar: Liste 5.10 deyimi Liste 5.11 içindeki deyimlere denktir. Liste 5.10. c l a s s Tak a t t r _ r e a d e r : tuk end Liste 5.11. 2 c l a s s Tak d e f tuk @tuk end end Liste 5.12 deyimi Liste 5.13 içindeki deyimlere denktir. Liste 5.12. c l a s s Tak a t t r _ r e a d e r : tuk end Liste 5.13. 2 c l a s s Tak d e f tuk ( d e ğ e r ) @tuk= d e ğ e r end end attr_reader ve attr_writer metotları yerine attr_accessor metodunu koyabiliriz. Böylece yazdığımız kodlar biraz daha kısalmış olur. Liste 5.14 deyimi Liste 5.15’deki deyimlere denktir. Liste 5.14. 5.5. ANLIK DEĞIŞKENLER 67 attr_accessor : x Liste 5.15. d e f x_ver=(x ) @x = x end 4 d e f x_al @x end Program 5.13. 3 8 c l a s s Kim a t t r _ r e a d e r : ad a t t r _ w r i t e r : ad end kim = Kim . new kim . ad = " Deniz " p kim . ad # => " Deniz " Program 5.13 içindeki attr_reader ve attr_writer metotları yerine attr_accessor metodunu koyarak yukarıda yazdığımız kodları biraz daha kısaltabiliriz. attr_accessor hem verici hem alıcı rolünü oynar. Program 5.14. 2 7 c l a s s Kim a t t r _ a c c e s s o r : ad end kim = Kim . new kim . ad = " Deniz " p kim . ad # => " Deniz " attr_acccessor ile alınan değişken değeri metin içine yerleştirilebilir (string interpolation): Program 5.15. #e n c o d i n g UTF−8 3 8 c l a s s Kim a t t r _ a c c e s s o r : ad d e f i n i t i a l i z e ( ad ) @name = ad end BÖLÜM 5. DEĞIŞKENLER 68 13 d e f selam p u t s " Merhaba , #{@name} " end end kim = Kim . new ( " L e y l a " ) kim . selam Liste 5.16. c l a s s Nokta3 attr_accessor : x , : y end # v e r i c i ve a l ı c ı metot y e r i n e g e ç e r Liste 5.17. 2 c l a s s Nokta3 attr_reader : x , : y end # a l ı c ı metot y e r i n e g e ç e r Liste 5.18. 2 c l a s s Nokta3 attr_writer : x , : y end 5.6 # v e r i c i metot y e r i n e g e ç e r Yerel değişkenler Yerel değişken adı ([a..z]) aralığındaki küçük harflerden biriyle ya da alt_çizgi (_) ile başlar. Bu biçimde başlayan her ad ya bir yerel değişkendir ya da bir metot adıdır. Yerel değişkenlerin öntakıları olmadığı için, Ruby onları metot adı gibi görebilir (çünkü metotların da öntakıları yoktur). Ancak yerel değişkene bir değer atandığını görürse, onun bir metot değil, bir yerel değişken olduğunu anlar. Değer atanmamış yerel değişkeni metotmuş gibi işlemeye çalışır. Aynı adla bir metot yoksa NameError hata iletisini verir. Dolayısıyla, yerel değişkenlere mutlaka değer atanmalıdır. Genel kural olarak, değer atanmamış değişkenler nil sayılır. Örneğin, a değişkeni aşağıdaki gibi tanımlı ve b hiç bildirilmemiş olsun. Ruby’nin yanıtları şöyle olur: Liste 5.19. 2 a = 0.0 i f print a print b f a l s e # deyimi a s l a işle nmez # => n i l ; d e ğ i ş k e n var , ama d e ğ e r atanmamış # => NameError ; b a d l ı b i r d e ğ i ş k e n ya da metot y o k t u r . 5.6. YEREL DEĞIŞKENLER 69 Yerel değişkenler, bir bakıma parametresiz ve gövdesiz metotlardır. Örnek: gider Bir blok içinde atanan yerel değişkenin sözkonusu değeri yalnızca o blok içinde geçerlidir. O nedenle, onlara o blok için yerel değişken denilir. Örneğin, Liste 5.20’in 2.satırındaki x değişkeni sayı_yaz metodunun bir yerel değişkenidir. Bu değişkene metot dışında erişilemez. Metot içindeki kodlar da metot bloku dışında kalan öğelere erişemez. Liste 5.20. 2 d e f sayı_yaz x = 7 p x # 7 yazar end sayı_yaz 7 # p x # y e r e l d e ğ i ş k e n e a i t olduğu metot d ı ş ı n d a n e r i ş i l e m e z . Şimdi Program 5.20 ’te biraz değişiklik yapalım. Biri sayı_yaz metodu içinde, ötekisi dışında olan iki tane x değişkeni tanımlayalım. Öntakıları olmadığı için her ikisi de yerel değişkendir. Ama geçerlilik bölgeleri farklıdır. Bu iki x değişkeni birbirlerinden farklıdırlar; yani ana bellekte farklı yerlerde konuşlanırlar. x = 7 sayı_yaz metodu içinde geçerlidir. x = 3 ise sayı_yaz metodunun dışındadır, dolayısıyla ait olduğu blok içinde geçerlidir. Genel kural olarak, bir nesnenin kapsanma alanı (scope) ait olduğu bloktur. Dolayısıyla sayı_yaz metodu içinden x = 3 yerel değişkenine erişilemez. Çünkü, x=3 değişkeni sayı_yaz bloku içinde değildir. Tersine olarak, x = 7 değişkenine sayı_yaz bloku dışından erişilemez. Liste 5.21. x = 3 2 d e f sayı_yaz x = 7 p x end # => 7 7 sayı_yaz p x # => 3 ; buradan $x=7$ d e ğ i ş k e n i n e e r i ş i l e m e z . Değişkene, ait olduğu blok dışından erişim isteniyorsa, yerel değişken yerine, istenen kapsanma alanına (scope) göre global, sınıf ya da anlık değişken tanımlanmalıdır. O tür değişkenlere erişimin nasıl yapıldığını yukarıda gördük. BÖLÜM 5. DEĞIŞKENLER 70 5.7 Değişkenimsiler (Pseudo variables) Ruby’de özel işlevleri olan bazı değişkenler vardır. Bunlara değişkenimsi (pseudo variable) denilir. Çok kullanılan değişkenimsilerden bazıları şunlardır: self Etkin (current) nesneye erişimi sağlar. nil : NilClass sınıfından ütretilen biricik nesne false : FalseClass sınıfından üretilen biricik nesne __FILE__ : Etkin (current) kaynak dosya. __LINE__ : Kaynak dosyada etkin (current) satır. Değişkenimsilerin değerleri değiştirilemez; değiştirilmek istenirse hata yapıldığı uyarısı gelir. self kullanımına örnekler Aşağıdakiler self’in bazı kullanılış biçimlerini gösteriyor. Program 5.16. #e n c o d i n g UTF−8 5 10 15 c l a s s Post attr_writer : kitap_adı d e f kitap_adı_yaz p u t s "Bu k i t a b ı n a d ı : end end p s t = Post . new p s t . k i t a p _ a d ı = " Ruby ’ e G i r i ş " p s t . kitap_adı_yaz # => "Bu k i t a b ı n a d ı : Ruby ’ ye G i r i ş " Program 5.17. #e n c o d i n g UTF−8 4 #{@kitap_adı } " c l a s s Post d e f s e l f . yazar_adı_yaz 5.7. DEĞIŞKENIMSILER (PSEUDO VARIABLES) 71 p u t s " Bütün e−p o s t a l a r ı Cihan y a z ı y o r " end end 9 Post . yazar_adı_yaz # => " Bütün e−p o s t a l a r ı Cihan y a z ı y o r " Program 5.18. # c l a s s << s e l f d e ğ i ş k e n ya da metodun s ı n ı f a 5 a i t olduğunu v u r g u l a r . c l a s s Post c l a s s << s e l f d e f yazar_adı_yaz p u t s " Bütün e−p o s t a l a r ı Cihan y a z ı y o r " end end end 10 Post . yazar_adı_yaz # " Bütün e−p o s t a l a r ı Cihan y a z ı y o r " nil kullanımına örnekler Tekli NilClass sınıfından türeyen tek nesnedir. Hiçlik, varolmayış anlamına gelir. nil? Ruby’de bir metottur. nil? metodu bir nesnenin nil olup olmadığını belirlemeye yarar. nil’den başka hiç bir nesne nil değildir. 3 Integer . n i l String . n i l " Ankara " . n i l 12. n i l " Ankara " . n i l nil . nil ? # # # # # # => => => => => => false false false false false true Program 5.19. 4 i f obj . n i l ? p u t s " B i r n e s n e yok ! " else obj . display_info () end > nil . class => N i l C l a s s 5 > n i l == n i l => t r u e > 5. n i l ? => f a l s e BÖLÜM 5. DEĞIŞKENLER 72 10 > [1 , 2 , 3]. n i l ? => f a l s e > { : a => 1 } [ : b ] . n i l ? => t r u e 15 > nil . nil ? => t r u e true, false true ve false, sırasıyla, tekli (singleton) TrueClass ve FalseClass sınıflarından üreretilen biricik (single) nesnelerdir. Mantıksal ifadelerin doğru mu yoksa yanlış mı olduğunu belirlemeye yararlar. 3 5== 5 5 < 3 5 > 3 # => t r u e # => f a l s e # => t r u e 5.7.1 Geçerlik Bölgesini Belirleme Bir x değişkeninin geçerli olduğu bölgeyi belirlemek için defined? x deyimini kullanırız. Program 5.20. 2 7 x = 10 => 10 defined ? x => " l o c a l −v a r i a b l e " $x = 10 => 10 d e f i n e d ? $x => " g l o b a l −v a r i a b l e "
© Copyright 2024 Paperzz