Ruby'de bir değişkenin türünü, adının ilk karakteri belirler: küçük harf veya alt çizgiyle başlayan adlar yerel değişken, @ ile başlayanlar örnek değişkeni, @@ ile başlayanlar sınıf değişkeni, $ ile başlayanlar global değişken, büyük harfle başlayanlar ise sabit olur. Değişken tanımlamak için var veya let gibi bir anahtar kelime yoktur; ilk atama değişkeni oluşturur.
Bu yazıda her değişken türünün kapsamını, hiç atanmamışken ne döndürdüğünü ve en sık karşılaşılan tuzakları resmî Assignment belgesi temelinde, Ruby 4.0 ile çalıştırılmış örneklerle anlatıyoruz. Serinin genel planı için Ruby öğrenme rehberi sayfasına bakabilirsiniz.
Değişken türlerine genel bakış

| Tür | Önek | Örnek | Nerede görünür | Atanmamışsa |
|---|---|---|---|---|
| Yerel değişken | küçük harf veya _ | toplam | Tanımlandığı metot, blok veya dosya | Metot çağrısı sanılır, NameError |
| Örnek değişkeni | @ | @deger | Aynı nesnenin tüm metotları | nil |
| Sınıf değişkeni | @@ | @@adet | Sınıf, alt sınıfları ve örnekleri | NameError |
| Global değişken | $ | $istek_sayisi | Programın her yeri | nil |
| Sabit | Büyük harf | MAKS_DENEME | Tanımlandığı sınıf veya modül ve iç içe kapsamlar | NameError |
Yerel değişkenler
Yerel değişken adı küçük bir ASCII harfle başlar; harf, rakam ve alt çizgi içerebilir. Belgeler, sekizinci biti dolu karakterlere de izin verildiğini belirtir; bu yüzden UTF-8 dosyalarda şehir gibi Türkçe harfli adlar çalışır. Yine de takım çalışmasında herkesin klavyesinde kolayca yazılabilen ASCII adlar tercih edilir. Belgelerdeki örnekler de kelimeleri alt çizgiyle ayıran big_calculation biçimini kullanır.
Bir blok (do ... end veya süslü parantez) yeni bir kapsam açar. Bloğun içinde oluşturulan değişken dışarı sızmaz, ancak dışarıda tanımlı bir değişken bloğun içinden görülür ve değiştirilebilir:
toplam = 0
[10, 20, 30].each do |sayi|
toplam += sayi
son = sayi
end
p toplam # çıktı: 60
p defined?(son) # çıktı: nil
şehir = "İzmir"
p şehir # çıktı: "İzmir"Önemli bir ayrıntı: yerel değişken, atama satırı çalıştığında değil, ayrıştırıcı (parser) atamayı gördüğünde oluşur. Aşağıdaki atama hiç çalışmaz, ama a yine de yerel değişken olarak kaydedilir ve değeri nil olur:
a = 5 if false
p local_variables # çıktı: [:a]
p a # çıktı: nilYerel değişken mi, metot mu?
Ruby'de parantezsiz metot çağrısı ile yerel değişken aynı görünür. Ayrıştırıcı bir ada daha önce atama yapılmadığını görürse onu metot çağrısı sayar. Modifier if ile yazılan şu satır bu yüzden hata verir: önce soldaki deger okunur ve henüz atama görülmediği için metot sanılır, ardından sağdaki atama çalışır, sonra var olmayan metot çağrılmaya çalışılır.
begin
p deger if deger = 0.zero?
rescue NameError => e
puts e.class # çıktı: NameError
puts e.message # çıktı: undefined local variable or method 'deger' for main
endÇözüm, atamayı ayrı bir satıra almak veya uzun if ... end biçimini kullanmaktır. Aynı ada sahip bir metodu yerel değişken varken çağırmak isterseniz self.ad yazın veya boş parantez ekleyin: ad().
Örnek değişkenleri (@)
@ ile başlayan örnek değişkenleri, bir nesnenin durumunu tutar. Aynı nesnenin bütün metotları bu değişkenleri paylaşır, ama her nesnenin kendi kopyası vardır. Hiç atanmamış bir örnek değişkeni okunduğunda hata vermez, nil döner. Sınıfların ayrıntıları Ruby class ve nesneler yazısında.
class Sayac
def initialize(baslangic)
@deger = baslangic
end
def artir
@deger += 1
end
def aciklama
@aciklama
end
end
s1 = Sayac.new(0)
s2 = Sayac.new(100)
s1.artir
s1.artir
p s1.artir # çıktı: 3
p s2.artir # çıktı: 101
p s1.aciklama # çıktı: nil
p s1.instance_variables # çıktı: [:@deger]Örnek değişkenine dışarıdan erişmek için genellikle attr_accessor kullanılır; bu, okuma ve fiyat= biçiminde yazma metotları üretir. Burada sık yapılan bir hata vardır: metot içinde alıcı belirtmeden fiyat = 50 yazarsanız Ruby bunu yazma metodu değil, yeni bir yerel değişken sayar. Yazma metodunu çağırmak için self. öneki şarttır:
class Urun
attr_accessor :fiyat
def indirim_yanlis
fiyat = 50 # yalnızca yerel bir değişken oluşturur
end
def indirim_dogru
self.fiyat = 50 # fiyat= metodunu çağırır
end
end
u = Urun.new
u.fiyat = 100
u.indirim_yanlis
p u.fiyat # çıktı: 100
u.indirim_dogru
p u.fiyat # çıktı: 50Sınıf değişkenleri (@@)
@@ ile başlayan sınıf değişkenleri bir sınıf, onun alt sınıfları ve tüm örnekleri arasında tek bir değer olarak paylaşılır. Alt sınıf değeri değiştirdiğinde üst sınıf da yeni değeri görür. Atanmamış bir sınıf değişkenini okumak, örnek değişkenlerinden farklı olarak NameError fırlatır.
class Arac
@@adet = 0
def initialize
@@adet += 1
end
def self.adet
@@adet
end
end
class Kamyon < Arac
end
Arac.new
Kamyon.new
Kamyon.new
p Arac.adet # çıktı: 3
p Kamyon.adet # çıktı: 3
class Bos
def self.oku
@@yok
end
end
begin
Bos.oku
rescue NameError => e
puts e.message # çıktı: uninitialized class variable @@yok in Bos
endBelgeler bir karışıklığa özellikle dikkat çeker: sınıflar da birer nesne olduğu için sınıf gövdesinde yazılan @ortam gibi bir değişken, sınıf değişkeni değil sınıf nesnesinin örnek değişkenidir. Bu değişken alt sınıflarla paylaşılmaz:
class Ayar
@ortam = "üretim"
class << self
attr_reader :ortam
end
end
class AltAyar < Ayar
end
p Ayar.ortam # çıktı: "üretim"
p AltAyar.ortam # çıktı: nilGlobal değişkenler ($)

$ ile başlayan değişkenlere programın her yerinden erişilir; atanmamışsa değerleri nil olur. Her yerden değiştirilebildikleri için hangi kodun değeri değiştirdiğini izlemek zorlaşır; bu yüzden kendi verileriniz için genellikle sabit, örnek değişkeni veya metot parametresi daha anlaşılır bir seçimdir.
$istek_sayisi = 0
def istek_al
$istek_sayisi += 1
end
3.times { istek_al }
p $istek_sayisi # çıktı: 3
p $tanimsiz # çıktı: nilRuby'nin önceden tanımladığı global değişkenler ise günlük kodda sık görülür. Pre-Defined Global Variables belgesi bunları gruplar halinde listeler: son eşleşmenin bilgisi ($~, $1, $2), son yakalanan istisna ($!), standart akışlar ($stdout, $stderr), program adı ($0) gibi.
"Tarih: 2026-11-07" =~ /(\d+)-(\d+)-(\d+)/
p $~[0] # çıktı: "2026-11-07"
p $1 # çıktı: "2026"
p $3 # çıktı: "07"
p $stdout == STDOUT # çıktı: true| Değişken | İçerdiği | Salt okunur mu |
|---|---|---|
| $! | Son yükseltilen istisna nesnesi veya nil | Evet |
| $~ | Son başarılı eşleşmenin MatchData nesnesi | Hayır |
| $1, $2, ... | Son eşleşmenin yakalama grupları | Evet |
| $stdout, $stderr | Standart çıktı ve hata akışı | Hayır |
| $0 | Çalışan programın adı | Hayır |
| $LOAD_PATH | require için aranan klasörler | Evet |
Sabitler
Büyük harfle başlayan her ad bir sabittir; sınıf ve modül adları da birer sabittir. Ruby'de sabitler aslında yeniden atanabilir, ancak yorumlayıcı bunu bir uyarıyla bildirir. Program çalışmaya devam eder ve sabit yeni değeri alır:
MAKS_DENEME = 3
MAKS_DENEME = 5
p MAKS_DENEME # çıktı: 5ornek.rb:2: warning: already initialized constant MAKS_DENEME
ornek.rb:1: warning: previous definition of MAKS_DENEME was here
5Uyarı yalnızca sabitin başka bir nesneye bağlanmasında çıkar. Sabitin gösterdiği nesnenin içeriğini değiştirmek hiçbir uyarı üretmez. İçeriğin değişmesini engellemek için nesneyi freeze ile dondurmanız gerekir; ayrıntılar Ruby frozen string ve freeze yazısında.
RENKLER = ["kırmızı", "mavi"]
RENKLER << "yeşil"
p RENKLER # çıktı: ["kırmızı", "mavi", "yeşil"]
SABIT_LISTE = ["a", "b"].freeze
begin
SABIT_LISTE << "c"
rescue FrozenError => e
puts e.message # çıktı: can't modify frozen Array: ["a", "b"]
end
begin
OLMAYAN_SABIT
rescue NameError => e
puts e.message # çıktı: uninitialized constant OLMAYAN_SABIT
endBir metot gövdesinin içinde sabite değer atamaya çalışırsanız kod hiç çalışmaz; Ruby dosyayı ayrıştırırken SyntaxError verir ve mesajda dynamic constant assignment ifadesi geçer. Sabitler sınıf veya modül gövdesinde ya da dosyanın en üst seviyesinde tanımlanmalıdır.
Sabitler tanımlandıkları sınıf veya modülün ad alanına aittir. İç içe yazılmış bir modülün içinden dıştaki sabitler görülür; aynı adlı üst seviye sabite ulaşmak için başına :: konur. Ruby'nin kendi sabitleri de aynı kurala uyar; RUBY_VERSION çalışan sürümü verir:
LIMIT = 10
module Ayarlar
LIMIT = 50
def self.goster
[LIMIT, ::LIMIT]
end
end
p Ayarlar.goster # çıktı: [50, 10]
p Ayarlar::LIMIT # çıktı: 50
p RUBY_VERSION # çıktı: "4.0.9"Atama biçimleri
Bir atama ifadesinin sonucu her zaman atanan değerdir. Ruby birkaç kısa atama biçimi sunar: a += 2, a = a + 2 ile aynıdır ve +, -, *, /, %, **, &, |, ^, <<, >> için kullanılabilir. ||= değişken nil veya false ise atama yapar; &&= ise tam tersine, değer bu ikisinden biri değilse atar. Çoklu atama ile birden fazla değişkene tek satırda değer verilir, iki değişkenin değeri yer değiştirilir ve * ile kalan elemanlar toplanır.
a, b = 1, 2
a, b = b, a
p [a, b] # çıktı: [2, 1]
ilk, *kalan = [10, 20, 30, 40]
p ilk # çıktı: 10
p kalan # çıktı: [20, 30, 40]
x, (y, z) = 1, [2, 3]
p [x, y, z] # çıktı: [1, 2, 3]
liste = 1, 2, 3
p liste # çıktı: [1, 2, 3]
ayar = nil
ayar ||= "varsayılan"
ayar ||= "başka"
p ayar # çıktı: "varsayılan"
sayac = 5
sayac += 2
p sayac # çıktı: 7Sol tarafta sağdakinden az değişken varsa fazla değerler yok sayılır; yıldızlı değişken (*kalan) sol tarafın herhangi bir yerinde olabilir ama tek bir atamada yalnızca bir tane kullanılabilir. Belgeler a ||= 0 ifadesinin a = a || 0 yerine a || a = 0 gibi davrandığını not eder: değer zaten doluysa hiçbir atama yapılmaz.
Sık yapılan hatalar

- Yazma metodunu
self.olmadan çağırmak: metot içindefiyat = 50yerel değişken oluşturur, nesnenin durumunu değiştirmez. - Modifier
ifiçinde atama yapmak:p a if a = degerbiçimi, ayrıştırma sırası yüzündenNameErrorverir. - Sabitin değişmez olduğunu sanmak: yeniden atama yalnızca uyarı verir, içerik değişikliği ise hiç uyarı vermez. Gerçek koruma için
freezekullanın. - Sınıf değişkenini alt sınıftan bağımsız sanmak:
@@değişkeni tüm hiyerarşide tek bir değerdir. Sınıf başına ayrı değer istiyorsanız sınıf düzeyinde örnek değişkeni kullanın. - Blok içinde tanımlanan değişkeni dışarıda kullanmaya çalışmak: blok yeni kapsam açar. Değeri dışarıda kullanacaksanız değişkeni bloktan önce tanımlayın. Döngülerdeki kapsam farkı için Ruby döngüler yazısına bakın.
Sık Sorulan Sorular
Ruby'de değişken tanımlamak için anahtar kelime var mı?
Hayır. Bir ada ilk kez değer atamak, o kapsamda yerel değişkeni oluşturur. Türü de belirtmezsiniz; değişken herhangi bir nesneyi gösterebilir ve sonradan başka türde bir nesneye bağlanabilir.
Atanmamış bir örnek değişkeni neden hata vermiyor?
Belgelere göre atanmamış örnek değişkenleri ve global değişkenler nil değerine sahiptir. Sınıf değişkenleri ve sabitler için durum farklıdır; ikisi de atanmamışken okunduğunda NameError fırlatır.
Sabitin yeniden atanmasını tamamen engelleyebilir miyim?
Yeniden atama sözdizimi olarak engellenmez, yalnızca uyarı üretir. Pratikte sabitleri bir kez tanımlayıp gösterdikleri nesneyi freeze ile dondurmak, kazara değişikliklere karşı en etkili yoldur.
Değişken adlarında Türkçe karakter kullanabilir miyim?
Kaynak dosya UTF-8 olduğunda kullanabilirsiniz; belgeler sekizinci biti dolu karakterlere izin verir. Ancak büyük harfle başlayan bir ad sabit sayılacağı için, adı küçük harfle başlatmanız gerekir. Kodlama konusunun ayrıntıları Ruby encoding ve Türkçe karakter yazısında.
Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.
İlgili içerikler: Ruby öğrenme rehberi · Ruby veri tipleri ve literaller · Ruby class ve nesneler · Ruby frozen string ve freeze · Ruby blok ve yield