15. Erişim Denetimi

Daha önce Ruby'nin işlevlere değil sadece yöntemlere sahip olduğunu söylemiştik. Ancak sadece tek bir tür yöntem yoktur. Bu bölümde erişim yöntemleri'nden bahsedeceğiz.

Yöntemi, sınıf tanımlamasının içinde değil de, en üstte tanımladığımızı farz edelim. Bunun C gibi daha geleneksel bir dildeki işlevlerle aynı işi yapan bir yöntem olduğunu düşünürüz.

ruby> def kare(n)
    |    n * n
    | end
   :kare
ruby> kare (5)
 25

Yeni yöntemimiz hiç bir sınıfa bağlı değil gibi gözüküyor, ama aslında Ruby bu yöntemi tüm sınıfların süper sınıfı olan Object sınıfına verir. Sonuç olarak her nesne bu yöntemi nasıl kullanacağını bilir. Bu durum doğru gibi gözükebilir ama burada küçük bir nokta vardır: bu yöntem her sınıfın private (özel) yöntemdir. Bunun ne anlama geldiğinden bahsedeceğiz fakat bu durumun sonuçlarından bir tanesi de aşağıdaki gibi sadece işlev tarzında çağırabilmemizdir:

ruby> class Foo
    |   def dördüncü_kuvvet(x)
    |     kare(x) * kare(x)
    |   end
    | end
   :dördüncü_kuvvet
ruby> Foo.new.dördüncü_kuvvet 10
   10000

Bir nesnenin, yöntemini açıkça çağırmasına izin verilmez:

ruby> "Balık".kare(5)
ERR: private method `kare' called for "Balık":String

Bu durum daha geleneksel bir dildeki gibi işlev yazmamızı sağlarken, Ruby'nin saf 'nesneye yönelik' yapısını korumasına yardımcı olur (işlevler halen nesnelerin yöntemleridir, sadece alıcı üstü kapalı olarak self'tir.)

Önceki bölümlerde de vurguladığımız gibi nesneye yönelik yazılım geliştirmenin genel mantığı, belirtim ile gerçeklenimi birbirinden ayırmak ya da bir nesneden hangi görevleri yapması istendiği ve onun bunların nasıl yapabileceğiyle ilgilenmektir.

Bir nesnenin dahili işleri genelde kullanıcıdan saklanmalı, kullanıcı yalnızca neyin gidip geldiğiyle ilgilenmeli ve nesnenin kendi içinde neyi nasıl yaptığını bildiğine güvenmelidir.

Genelde nesnenin dış dünya tarafından görülmeyen ancak dahili olarak kullandığı yöntemlere sahip olması yararlı bir şeydir (ve bu durum kullacının nesneleri görme biçimi değiştirilmeksizin yazılımcının isteğine göre değiştirebilir).

Aşağıdaki basit örnekte motor sınıfının görünmediğini ama dahili olarak çalıştığını varsayalım.

ruby> class Deneme
    |    def iki_katı(a)
    |       print a," kere iki ",motor(a),"\n"
    |    end
    |    def motor(b)
    |       b * 2
    |    end
    |    private:motor  # motoru kullanıcılardan saklar
    | end
 Deneme
ruby> deneme = Deneme.new
   #<Deneme:0x000055e097e4f368>
ruby> deneme.motor(6)
ERR: private method `motor' called for #<Deneme:0x000055e097e4f368>
ruby> deneme.iki_katı(6)
6 kere iki 12.
   nil

deneme.motor(6)'nın 12 değerini döndürmesini umuyorduk ancak bir Deneme nesnesi gibi davrandığımızda motor'un erişilemez olduğunu gördük. Yalnızca iki_katı gibi diğer Deneme yöntemleri motor'a ulaşma hakkına sahiptir. Böylece öncelikle iki_katı yöntemini içeren genel arayüze gitmek zorunda bırakıldık. Yazılımcı, kullancının Deneme nesnelerinin birbirini nasıl etkilediğine bakmaksızın motor yöntemini (bu örnekte muhtemelen başarım açısından b*2'yi b+b ile) değiştirebilir. Bu örnek erişim denetimlerini anlatmak için tabii ki çok basit bir örnektir ancak daha karmaşık ve ilginç sınıflar üretmeye başlayınca erişim denetiminin ne kadar yararlı bir kavram olduğunu anlayacaksınız.