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.

Bir yöntemi, bir 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 square(n)
    |    n * n
    |  end
   nil
ruby>   square(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 yöntemidir. 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 dorduncu_kuvvet(x)
    |      square(x) * square(x)
    |    end
    |  end
   nil
ruby>   Foo.new.dorduncu_kuvvet 10
  10000

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

ruby>   "fish".square(5)
ERR: (eval):1: private method `square' called for "fish":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çekleştirimi birbirinden ayırmak, ya da bir nesnenin hangi görevleri yapmak istediği ve bunu 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 dair 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_kati(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:0x4017181c>
ruby>   deneme.motor(6)
ERR: (eval):1: private method motor' called for #<Deneme:0x4017181c>
ruby>   deneme.iki_kati(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_kati gibi diğer Deneme yöntemleri motor'a ulaşma hakkına sahiptir. Böylece öncelikle iki_kati 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.