Giriş: Nesne Yönelimli Programlamaya Genel Bakış
Ruby, tam anlamıyla nesne yönelimli bir programlama dilidir. Bu, Ruby'deki her şeyin – sayılar, dizeler, hatta true ve false değerleri bile – aslında birer nesne olduğu anlamına gelir. Nesne Yönelimli Programlama (NYP veya İngilizce adıyla OOP - Object-Oriented Programming), yazılım tasarımına bir paradigma sunar. Bu paradigma, gerçek dünyadaki varlıkları ve kavramları modellemek için 'nesneler' adı verilen soyut veri yapılarını kullanır. NYP'nin temel sütunları arasında enkapsülasyon, kalıtım ve çok biçimlilik (polimorfizm) bulunur. Ruby'de bu kavramlar, özellikle sınıflar ve nesneler aracılığıyla hayata geçirilir. Bu rehberde, Ruby'deki sınıfların ve nesnelerin derinliklerine inecek, nasıl çalıştıklarını, neden bu kadar önemli olduklarını ve günlük programlama pratiklerinizde onlardan en iyi şekilde nasıl faydalanacağınızı ayrıntılı bir şekilde inceleyeceğiz.
NYP, karmaşık sistemleri daha yönetilebilir, modüler ve anlaşılır hale getirme amacı güder. Bir programı nesneler etrafında organize etmek, kodun yeniden kullanılabilirliğini artırır, bakımı kolaylaştırır ve hataların izini sürmeyi basitleştirir. Ruby'nin bu felsefeyi benimsemesi, dili hem güçlü hem de öğrenmesi keyifli bir hale getirir.
Sınıflar: Nesnelerin Planı
Bir sınıf, tıpkı bir mimarın bina inşa etmeden önce çizdiği bir plan veya kalıp gibidir. Tek başına bir sınıf, programınızda somut bir şey yapmaz; ancak ondan oluşturulacak nesnelerin özelliklerini (veri) ve davranışlarını (metotlar) tanımlar. Ruby'de bir sınıf, `class` anahtar kelimesi kullanılarak tanımlanır.
Yukarıdaki örnekte, 'Ogrenci' adında boş bir sınıf tanımladık. Bir sınıfın içinde, o sınıftan oluşturulacak her nesnenin sahip olacağı verileri ve metotları belirtiriz.
Örnek Metotları (Instance Methods):
Nesneler, kendi üzerlerinde çalıştırılabilecek metotlara sahiptir. Bunlar genellikle örnek metotları olarak adlandırılır çünkü her bir sınıf örneği (nesne) bu metotlara erişebilir. Metotlar, nesnenin gerçekleştirebileceği eylemleri veya davranışları tanımlar.
İlklendirme Metodu: initialize
Ruby'de, bir nesne oluşturulduğunda otomatik olarak çağrılan özel bir metot vardır: `initialize`. Bu metot, nesnenin ilk durumunu ayarlamak için kullanılır ve genellikle kurucu metot (constructor) olarak adlandırılır. `initialize` metodunda tanımlanan parametreler, nesne oluşturulurken `new` metoduna iletilir.
Yukarıdaki örnekte, `@ad` ve `@numara` örnek değişkenleridir. Bir örnek değişkeni, o sınıftan oluşturulan her bir nesneye özgüdür. Her öğrencinin kendi adı ve numarası olacaktır.
Erişimciler (Accessors): attr_reader, attr_writer, attr_accessor
Örnek değişkenlerine doğrudan erişim sağlamak iyi bir uygulama değildir (enkapsülasyon ilkesi). Bunun yerine, bu değişkenlere erişim veya atama yapmak için metotlar (erişimciler) kullanırız. Ruby, bu tür metotları hızlıca oluşturmak için `attr_reader`, `attr_writer` ve `attr_accessor` makrolarını sağlar.
Artık bir öğrenci nesnesinin adına `ogrenci.ad` ile erişebilir ve sınıfını `ogrenci.sinif = "10B"` ile değiştirebiliriz.
Sınıf Metotları (Class Methods):
Sınıf metotları, sınıfın kendisi üzerinde çalışır, tek tek nesneler üzerinde değil. Genellikle belirli bir sınıfa ait genel işlevsellik veya nesne oluşturma alternatif yolları (factory methods) sağlamak için kullanılırlar. Bir sınıf metodu, metodun adının önüne `self.` veya sınıfın adını getirerek tanımlanır.
`@@toplam_ogrenci_sayisi` bir sınıf değişkenidir. Örnek değişkenlerinin aksine, sınıf değişkenleri o sınıfın tüm örnekleri tarafından paylaşılır. Tüm öğrenci nesneleri bu tek `@@toplam_ogrenci_sayisi` değişkenini kullanır ve değiştirir.
Nesneler: Sınıfın Somut Halleri
Bir nesne, bir sınıfın somut bir örneğidir. Tıpkı bir bina planından (sınıf) inşa edilen gerçek bir bina (nesne) gibi. Ruby'de bir nesneyi `new` metodunu çağırarak oluşturursunuz.
Her bir `ogrenci1` ve `ogrenci2` değişkeni, `Ogrenci` sınıfının ayrı birer nesnesini (örneğini) temsil eder. Her biri kendi `@ad`, `@numara` ve `@sinif` değerlerine sahiptir.
self Anahtar Kelimesi:
`self` anahtar kelimesi, mevcut nesneye (örnek metotları içinde) veya mevcut sınıfa (sınıf metotları içinde) referans verir. Genellikle, metotlar içinde örnek değişkenleriyle çakışan lokal değişkenler olduğunda kullanılır veya bir metottan başka bir metodu çağırmak gerektiğinde netlik sağlamak için kullanılır.
Kalıtım (Inheritance): Davranışları Genişletme
Kalıtım, bir sınıfın (alt sınıf veya çocuk sınıf), başka bir sınıfın (üst sınıf veya ebeveyn sınıf) özelliklerini ve davranışlarını miras almasına olanak tanıyan bir NYP ilkesidir. Bu, kodun yeniden kullanılabilirliğini artırır ve hiyerarşik bir yapı oluşturur. Ruby'de `<` sembolü ile kalıtım belirtilir.
super Anahtar Kelimesi:
Alt sınıfta `super` anahtar kelimesi, üst sınıfın aynı isimdeki metodunu çağırmak için kullanılır. Özellikle `initialize` metodu içinde, üst sınıfın başlatma mantığını çalıştırmak için sıkça kullanılır. Parametresiz çağrıldığında, `super` otomatik olarak geçerli metodun tüm parametrelerini üst metoda iletir.
Çok Biçimlilik (Polymorphism): Farklı Nesneler, Aynı Arayüz
Çok biçimlilik, farklı sınıflara ait nesnelerin aynı arayüzü paylaşabilmesi ve aynı metoda farklı şekillerde yanıt verebilmesi yeteneğidir. Ruby'de bu, temel olarak metot geçersiz kılma (method overriding) ve duck typing ile sağlanır.
Metot Geçersiz Kılma:
Bir alt sınıf, üst sınıfta tanımlanmış bir metodu kendi özel uygulamasıyla yeniden tanımlayabilir. Yukarıdaki `bilgileri_goster` metodu bu duruma güzel bir örnektir. Hem `Ogrenci` hem de `Ogretmen` sınıfları `Kisi` sınıfında olmayan kendi `bilgileri_goster` metotlarına sahiptirler. Eğer alt sınıflarda `bilgileri_goster` tanımlanmasaydı, üst sınıfın metodu çağrılırdı.
Bu örnekte, üç farklı nesne (`Kedi`, `Kopek`, `Hayvan`) aynı `konus` metodunu çağırıyor ancak her biri kendi türüne özgü bir yanıt veriyor. Bu, çok biçimliliğin gücünü gösterir.
Duck Typing:
Ruby'de, bir nesnenin belirli bir sınıfın örneği olup olmadığına bakılmaksızın, belirli bir metodu yanıtlayıp yanıtlamadığına odaklanılır. "Eğer ördek gibi yürüyorsa ve ördek gibi vakvaklıyorsa, o bir ördektir." Bu felsefe, Ruby'deki esnekliği artırır ve kalıtım hiyerarşileri yerine arayüzlere odaklanmayı teşvik eder.
Enkapsülasyon: Veri Saklama ve Koruma
Enkapsülasyon, bir nesnenin verilerini (örnek değişkenleri) ve bu veriler üzerinde çalışan metotları tek bir birim içinde bir araya getirme ve bu verilere dışarıdan doğrudan erişimi sınırlama ilkesidir. Bu, nesnenin iç durumunun yanlışlıkla değiştirilmesini önler ve kodun güvenilirliğini artırır. Ruby'de bu, `attr_accessor` gibi erişimciler ve `private` ile `protected` metotlar kullanılarak sağlanır.
private ve protected Metotlar:
Modüller (Modules): Mixin'ler ve Ad Alanları
Ruby'de modüller, sınıflara benzer ancak kendilerinden nesne oluşturulamaz. İki ana amaca hizmet ederler:
Bu örnekte, `Davranislar` modülü sayesinde hem `Sporcu` hem de `Kedi` sınıfları `kos` ve `zipla` metotlarına sahip olur. Bu, kod tekrarını önler ve daha modüler tasarımlar yapmamızı sağlar.
Sonuç: Ruby'de NYP'nin Gücü
Ruby'deki sınıflar ve nesneler, dilin nesne yönelimli doğasının temelini oluşturur. Sınıflar, nesneler için bir şablon görevi görürken, nesneler bu şablonların somutlaşmış halleridir. Kalıtım, çok biçimlilik ve enkapsülasyon gibi NYP ilkeleri, Ruby'nin güçlü ve esnek bir dil olmasını sağlar. Modüller ise bu yapıyı daha da genişleterek kodun yeniden kullanılabilirliğini ve organizasyonunu artırır.
Bu kavramları derinlemesine anlamak, sadece daha iyi Ruby kodları yazmanıza yardımcı olmakla kalmayacak, aynı zamanda genel olarak yazılım mühendisliği prensipleri hakkında daha sağlam bir kavrayış geliştirmenizi sağlayacaktır. Karmaşık sistemleri tasarlarken ve uygularken, sınıfların ve nesnelerin nasıl etkileşim kurduğunu bilmek, karşılaşılan sorunlara daha zarif ve sürdürülebilir çözümler bulmanızı sağlayacaktır. Unutmayın, iyi bir nesne yönelimli tasarım, kodun okunabilirliğini, bakımını ve genişletilebilirliğini doğrudan etkiler.
Daha fazla bilgi için Ruby resmi dokümantasyonunu ziyaret edebilirsiniz.
Bu rehberin, Ruby'deki sınıflar ve nesneler dünyasına girişinizde size yardımcı olduğunu umuyoruz. Pratik yapmaya devam edin ve kod yazmaktan çekinmeyin! Deneyim, en iyi öğretmendir.
Önemli Hatırlatma:
Ruby, tam anlamıyla nesne yönelimli bir programlama dilidir. Bu, Ruby'deki her şeyin – sayılar, dizeler, hatta true ve false değerleri bile – aslında birer nesne olduğu anlamına gelir. Nesne Yönelimli Programlama (NYP veya İngilizce adıyla OOP - Object-Oriented Programming), yazılım tasarımına bir paradigma sunar. Bu paradigma, gerçek dünyadaki varlıkları ve kavramları modellemek için 'nesneler' adı verilen soyut veri yapılarını kullanır. NYP'nin temel sütunları arasında enkapsülasyon, kalıtım ve çok biçimlilik (polimorfizm) bulunur. Ruby'de bu kavramlar, özellikle sınıflar ve nesneler aracılığıyla hayata geçirilir. Bu rehberde, Ruby'deki sınıfların ve nesnelerin derinliklerine inecek, nasıl çalıştıklarını, neden bu kadar önemli olduklarını ve günlük programlama pratiklerinizde onlardan en iyi şekilde nasıl faydalanacağınızı ayrıntılı bir şekilde inceleyeceğiz.
NYP, karmaşık sistemleri daha yönetilebilir, modüler ve anlaşılır hale getirme amacı güder. Bir programı nesneler etrafında organize etmek, kodun yeniden kullanılabilirliğini artırır, bakımı kolaylaştırır ve hataların izini sürmeyi basitleştirir. Ruby'nin bu felsefeyi benimsemesi, dili hem güçlü hem de öğrenmesi keyifli bir hale getirir.
Sınıflar: Nesnelerin Planı
Bir sınıf, tıpkı bir mimarın bina inşa etmeden önce çizdiği bir plan veya kalıp gibidir. Tek başına bir sınıf, programınızda somut bir şey yapmaz; ancak ondan oluşturulacak nesnelerin özelliklerini (veri) ve davranışlarını (metotlar) tanımlar. Ruby'de bir sınıf, `class` anahtar kelimesi kullanılarak tanımlanır.
Ruby:
class Ogrenci
# Sınıfın tanımı buraya gelir
end
Yukarıdaki örnekte, 'Ogrenci' adında boş bir sınıf tanımladık. Bir sınıfın içinde, o sınıftan oluşturulacak her nesnenin sahip olacağı verileri ve metotları belirtiriz.
Örnek Metotları (Instance Methods):
Nesneler, kendi üzerlerinde çalıştırılabilecek metotlara sahiptir. Bunlar genellikle örnek metotları olarak adlandırılır çünkü her bir sınıf örneği (nesne) bu metotlara erişebilir. Metotlar, nesnenin gerçekleştirebileceği eylemleri veya davranışları tanımlar.
Ruby:
class Ogrenci
def selamla
"Merhaba, ben bir öğrenciyim!"
end
end
İlklendirme Metodu: initialize
Ruby'de, bir nesne oluşturulduğunda otomatik olarak çağrılan özel bir metot vardır: `initialize`. Bu metot, nesnenin ilk durumunu ayarlamak için kullanılır ve genellikle kurucu metot (constructor) olarak adlandırılır. `initialize` metodunda tanımlanan parametreler, nesne oluşturulurken `new` metoduna iletilir.
Ruby:
class Ogrenci
def initialize(ad, numara)
@ad = ad # Örnek değişkeni
@numara = numara # Örnek değişkeni
end
def bilgileri_goster
"Ad: #{@ad}, Numara: #{@numara}"
end
end
Yukarıdaki örnekte, `@ad` ve `@numara` örnek değişkenleridir. Bir örnek değişkeni, o sınıftan oluşturulan her bir nesneye özgüdür. Her öğrencinin kendi adı ve numarası olacaktır.
Erişimciler (Accessors): attr_reader, attr_writer, attr_accessor
Örnek değişkenlerine doğrudan erişim sağlamak iyi bir uygulama değildir (enkapsülasyon ilkesi). Bunun yerine, bu değişkenlere erişim veya atama yapmak için metotlar (erişimciler) kullanırız. Ruby, bu tür metotları hızlıca oluşturmak için `attr_reader`, `attr_writer` ve `attr_accessor` makrolarını sağlar.
[li]`attr_reader`: Sadece okuma (get) metodu oluşturur.[/li]
[li]`attr_writer`: Sadece yazma (set) metodu oluşturur.[/li]
[li]`attr_accessor`: Hem okuma hem de yazma (get ve set) metotları oluşturur.[/li]
Ruby:
class Ogrenci
attr_reader :ad # Okuma metodu Ogrenci#ad oluşturur
attr_writer :numara # Yazma metodu Ogrenci#numara= oluşturur
attr_accessor :sinif # Okuma ve yazma metotları Ogrenci#sinif, Ogrenci#sinif= oluşturur
def initialize(ad, numara, sinif)
@ad = ad
@numara = numara
@sinif = sinif
end
def bilgileri_goster
"Ad: #{@ad}, Numara: #{@numara}, Sınıf: #{@sinif}"
end
end
Artık bir öğrenci nesnesinin adına `ogrenci.ad` ile erişebilir ve sınıfını `ogrenci.sinif = "10B"` ile değiştirebiliriz.
Sınıf Metotları (Class Methods):
Sınıf metotları, sınıfın kendisi üzerinde çalışır, tek tek nesneler üzerinde değil. Genellikle belirli bir sınıfa ait genel işlevsellik veya nesne oluşturma alternatif yolları (factory methods) sağlamak için kullanılırlar. Bir sınıf metodu, metodun adının önüne `self.` veya sınıfın adını getirerek tanımlanır.
Ruby:
class Ogrenci
attr_accessor :ad, :numara, :sinif
@@toplam_ogrenci_sayisi = 0 # Sınıf değişkeni
def initialize(ad, numara, sinif)
@ad = ad
@numara = numara
@sinif = sinif
@@toplam_ogrenci_sayisi += 1 # Her yeni nesne oluşturulduğunda artır
end
def self.toplam_sayi
@@toplam_ogrenci_sayisi
end
def self.en_populer_sinif
# Bu metodun mantığı daha karmaşık olabilir
"10A"
end
end
`@@toplam_ogrenci_sayisi` bir sınıf değişkenidir. Örnek değişkenlerinin aksine, sınıf değişkenleri o sınıfın tüm örnekleri tarafından paylaşılır. Tüm öğrenci nesneleri bu tek `@@toplam_ogrenci_sayisi` değişkenini kullanır ve değiştirir.
Nesneler: Sınıfın Somut Halleri
Bir nesne, bir sınıfın somut bir örneğidir. Tıpkı bir bina planından (sınıf) inşa edilen gerçek bir bina (nesne) gibi. Ruby'de bir nesneyi `new` metodunu çağırarak oluşturursunuz.
Ruby:
ogrenci1 = Ogrenci.new("Ali", "123", "9A")
ogrenci2 = Ogrenci.new("Ayşe", "456", "10B")
puts ogrenci1.bilgileri_goster # => "Ad: Ali, Numara: 123, Sınıf: 9A"
puts ogrenci2.bilgileri_goster # => "Ad: Ayşe, Numara: 456, Sınıf: 10B"
puts Ogrenci.toplam_sayi # => 2
Her bir `ogrenci1` ve `ogrenci2` değişkeni, `Ogrenci` sınıfının ayrı birer nesnesini (örneğini) temsil eder. Her biri kendi `@ad`, `@numara` ve `@sinif` değerlerine sahiptir.
self Anahtar Kelimesi:
`self` anahtar kelimesi, mevcut nesneye (örnek metotları içinde) veya mevcut sınıfa (sınıf metotları içinde) referans verir. Genellikle, metotlar içinde örnek değişkenleriyle çakışan lokal değişkenler olduğunda kullanılır veya bir metottan başka bir metodu çağırmak gerektiğinde netlik sağlamak için kullanılır.
Ruby:
class Urun
attr_accessor :ad, :fiyat
def initialize(ad, fiyat)
@ad = ad
@fiyat = fiyat
end
def indirim_uygula(oran)
self.fiyat = self.fiyat * (1 - oran) # self.fiyat, attr_accessor tarafından oluşturulan metodu çağırır
end
def kendini_tanit
"Ben bir #{self.class} nesnesiyim. Adım #{self.ad}."
end
end
urun = Urun.new("Klavye", 200)
puts urun.kendini_tanit # => "Ben bir Urun nesnesiyim. Adım Klavye."
urun.indirim_uygula(0.10)
puts urun.fiyat # => 180.0
Kalıtım (Inheritance): Davranışları Genişletme
Kalıtım, bir sınıfın (alt sınıf veya çocuk sınıf), başka bir sınıfın (üst sınıf veya ebeveyn sınıf) özelliklerini ve davranışlarını miras almasına olanak tanıyan bir NYP ilkesidir. Bu, kodun yeniden kullanılabilirliğini artırır ve hiyerarşik bir yapı oluşturur. Ruby'de `<` sembolü ile kalıtım belirtilir.
Ruby:
class Kisi
attr_accessor :ad, :soyad
def initialize(ad, soyad)
@ad = ad
@soyad = soyad
end
def tam_ad
"#{@ad} #{@soyad}"
end
end
class Ogrenci < Kisi # Ogrenci, Kisi'den miras alır
attr_accessor :okul_no
def initialize(ad, soyad, okul_no)
super(ad, soyad) # Üst sınıfın initialize metodunu çağırır
@okul_no = okul_no
end
def bilgileri_goster
"#{tam_ad} (Okul No: #{@okul_no})"
end
end
class Ogretmen < Kisi # Ogretmen de Kisi'den miras alır
attr_accessor :brans
def initialize(ad, soyad, brans)
super(ad, soyad)
@brans = brans
end
def bilgileri_goster
"#{tam_ad} (Branş: #{@brans})"
end
end
ogrenci = Ogrenci.new("Burak", "Yılmaz", "5005")
ogretmen = Ogretmen.new("Zeynep", "Demir", "Matematik")
puts ogrenci.bilgileri_goster # => "Burak Yılmaz (Okul No: 5005)"
puts ogretmen.bilgileri_goster # => "Zeynep Demir (Branş: Matematik)"
super Anahtar Kelimesi:
Alt sınıfta `super` anahtar kelimesi, üst sınıfın aynı isimdeki metodunu çağırmak için kullanılır. Özellikle `initialize` metodu içinde, üst sınıfın başlatma mantığını çalıştırmak için sıkça kullanılır. Parametresiz çağrıldığında, `super` otomatik olarak geçerli metodun tüm parametrelerini üst metoda iletir.
Çok Biçimlilik (Polymorphism): Farklı Nesneler, Aynı Arayüz
Çok biçimlilik, farklı sınıflara ait nesnelerin aynı arayüzü paylaşabilmesi ve aynı metoda farklı şekillerde yanıt verebilmesi yeteneğidir. Ruby'de bu, temel olarak metot geçersiz kılma (method overriding) ve duck typing ile sağlanır.
Metot Geçersiz Kılma:
Bir alt sınıf, üst sınıfta tanımlanmış bir metodu kendi özel uygulamasıyla yeniden tanımlayabilir. Yukarıdaki `bilgileri_goster` metodu bu duruma güzel bir örnektir. Hem `Ogrenci` hem de `Ogretmen` sınıfları `Kisi` sınıfında olmayan kendi `bilgileri_goster` metotlarına sahiptirler. Eğer alt sınıflarda `bilgileri_goster` tanımlanmasaydı, üst sınıfın metodu çağrılırdı.
Ruby:
class Hayvan
def konus
"(Ses çıkarır)"
end
end
class Kedi < Hayvan
def konus
"Miyav!"
end
end
class Kopek < Hayvan
def konus
"Hav hav!"
end
end
dizi = [Kedi.new, Kopek.new, Hayvan.new]
dizi.each do |hayvan|
puts hayvan.konus
end
# Çıktı:
# Miyav!
# Hav hav!
# (Ses çıkarır)
Bu örnekte, üç farklı nesne (`Kedi`, `Kopek`, `Hayvan`) aynı `konus` metodunu çağırıyor ancak her biri kendi türüne özgü bir yanıt veriyor. Bu, çok biçimliliğin gücünü gösterir.
Duck Typing:
Ruby'de, bir nesnenin belirli bir sınıfın örneği olup olmadığına bakılmaksızın, belirli bir metodu yanıtlayıp yanıtlamadığına odaklanılır. "Eğer ördek gibi yürüyorsa ve ördek gibi vakvaklıyorsa, o bir ördektir." Bu felsefe, Ruby'deki esnekliği artırır ve kalıtım hiyerarşileri yerine arayüzlere odaklanmayı teşvik eder.
"Eğer ördek gibi yürüyorsa ve ördek gibi vakvaklıyorsa, o bir ördektir."
Enkapsülasyon: Veri Saklama ve Koruma
Enkapsülasyon, bir nesnenin verilerini (örnek değişkenleri) ve bu veriler üzerinde çalışan metotları tek bir birim içinde bir araya getirme ve bu verilere dışarıdan doğrudan erişimi sınırlama ilkesidir. Bu, nesnenin iç durumunun yanlışlıkla değiştirilmesini önler ve kodun güvenilirliğini artırır. Ruby'de bu, `attr_accessor` gibi erişimciler ve `private` ile `protected` metotlar kullanılarak sağlanır.
private ve protected Metotlar:
[li]`private` Metotlar: Sadece tanımlandıkları sınıfın içinde, başka metotlar tarafından çağrılabilirler. Doğrudan alıcı nesne (receiver) belirtilerek çağrılamazlar. Yani `self.metot` şeklinde değil, sadece `metot` şeklinde çağrılırlar.[/li]
[li]`protected` Metotlar: Tanımlandıkları sınıfın ve alt sınıfların örnekleri tarafından çağrılabilirler. Ancak bu çağrılar sadece kendi sınıfından veya alt sınıflarından bir nesne üzerinden `self` veya başka bir aynı tip nesne üzerinden yapılabilir.[/li]
Ruby:
class Hesap
def initialize(bakiye)
@bakiye = bakiye
end
def cek(miktar)
if miktar <= @bakiye
@bakiye -= miktar
puts "#{miktar} TL çekildi. Yeni bakiye: #{@bakiye} TL."
else
puts "Yetersiz bakiye. Mevcut bakiye: #{@bakiye} TL."
end
end
def goster_bakiye
gizli_bakiye # Sadece sınıf içinden çağrılabilir
end
private
def gizli_bakiye
"Mevcut bakiye (gizli): #{@bakiye} TL."
end
end
hesap = Hesap.new(1000)
hesap.cek(300)
# puts hesap.gizli_bakiye # Hata verecektir: private method `gizli_bakiye' called
puts hesap.goster_bakiye # => Mevcut bakiye (gizli): 700 TL.
Modüller (Modules): Mixin'ler ve Ad Alanları
Ruby'de modüller, sınıflara benzer ancak kendilerinden nesne oluşturulamaz. İki ana amaca hizmet ederler:
[li] Mixin'ler (Mixins): Ortak davranışları birden fazla sınıfa karıştırmak (inject) için kullanılırlar. Ruby, çoklu kalıtımı doğrudan desteklemez, ancak modüller bu işlevi mixin'ler aracılığıyla sağlar. Bir modülü bir sınıfa dahil etmek için `include` anahtar kelimesi kullanılır.[/li]
[li] Ad Alanları (Namespaces): İsim çakışmalarını önlemek ve ilgili sınıfları, metotları ve sabitleri mantıksal olarak gruplandırmak için kullanılırlar.[/li]
Ruby:
module Davranislar
def kos
"Koşuyorum!"
end
def zipla
"Zıplıyorum!"
end
end
class Sporcu
include Davranislar # Modülü dahil et
def antrenman_yap
puts kos
puts zipla
"Antrenman bitti."
end
end
class Kedi
include Davranislar # Kedi de aynı davranışları kazanır
def miyavla
"Miyav!"
end
end
sporcu = Sporcu.new
kedi = Kedi.new
puts sporcu.antrenman_yap
# Çıktı:
# Koşuyorum!
# Zıplıyorum!
# Antrenman bitti.
puts kedi.kos # => "Koşuyorum!"
Bu örnekte, `Davranislar` modülü sayesinde hem `Sporcu` hem de `Kedi` sınıfları `kos` ve `zipla` metotlarına sahip olur. Bu, kod tekrarını önler ve daha modüler tasarımlar yapmamızı sağlar.
Sonuç: Ruby'de NYP'nin Gücü
Ruby'deki sınıflar ve nesneler, dilin nesne yönelimli doğasının temelini oluşturur. Sınıflar, nesneler için bir şablon görevi görürken, nesneler bu şablonların somutlaşmış halleridir. Kalıtım, çok biçimlilik ve enkapsülasyon gibi NYP ilkeleri, Ruby'nin güçlü ve esnek bir dil olmasını sağlar. Modüller ise bu yapıyı daha da genişleterek kodun yeniden kullanılabilirliğini ve organizasyonunu artırır.
Bu kavramları derinlemesine anlamak, sadece daha iyi Ruby kodları yazmanıza yardımcı olmakla kalmayacak, aynı zamanda genel olarak yazılım mühendisliği prensipleri hakkında daha sağlam bir kavrayış geliştirmenizi sağlayacaktır. Karmaşık sistemleri tasarlarken ve uygularken, sınıfların ve nesnelerin nasıl etkileşim kurduğunu bilmek, karşılaşılan sorunlara daha zarif ve sürdürülebilir çözümler bulmanızı sağlayacaktır. Unutmayın, iyi bir nesne yönelimli tasarım, kodun okunabilirliğini, bakımını ve genişletilebilirliğini doğrudan etkiler.
Daha fazla bilgi için Ruby resmi dokümantasyonunu ziyaret edebilirsiniz.
Bu rehberin, Ruby'deki sınıflar ve nesneler dünyasına girişinizde size yardımcı olduğunu umuyoruz. Pratik yapmaya devam edin ve kod yazmaktan çekinmeyin! Deneyim, en iyi öğretmendir.
"Programlamada en iyi yol, yazmaya devam etmektir." - Anonim
Önemli Hatırlatma:
[li]Ruby'de her şey bir nesnedir.[/li]
[li]Sınıflar, nesnelerin şablonlarıdır.[/li]
[li]Nesneler, sınıfların örnekleridir.[/li]
[li]Örnek değişkenleri (`@`) nesneye özgüdür.[/li]
[li]Sınıf değişkenleri (`@@`) tüm sınıf örnekleri tarafından paylaşılır.[/li]
[li]Kalıtım (`<`) kodun tekrarını azaltır.[/li]
[li]Modüller (`include`) çoklu kalıtım benzeri özellikler sağlar ve ad alanları oluşturur.[/li]