Değişkenler 5.1 Atama

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 "