sınıfın yalnızca belirli öğelerine arkadaşlık vermek (attorney client idiyomu)

Nesne yönelimli programlamanın temel niteliklerinden birisi, belki de en önemlisi “encapsulation” (kapsülleme) . C++ gibi dillerde sınıfın private bölümü üzerinde uygulanan erişim kontrolü kapsüllemeye büyük ölçüde destek oluyor.  Sınıf nesnesinin kullandığı verileri ve sınıf nesnesinin verdiği hizmetlere ilişkin kodları sınıfın private bölümüne koyarak bu öğeleri hizmet alan kodlardan yalıtmış oluyoruz. Yani arayüz (interface) ile kodu (implementation) birbirinden ayırıyoruz. Ancak öyle durumlar var ki sınıfın private bölümüne sınıfın kendi kodlarının dışında bazı kodların erişebilmesi en iyi çözüm haline gelebiliyor. Şüphesiz, bir sınıfın private bölümünü başka kodların erişimine açmak, kodların birbirine bağlılığını (coupling) arttırıyor. Ancak ne yapalım, bazen buna katlanmak zorunda kalıyoruz.

C++ dilinde arkadaşlık (friend’lik) bildirimi ile bir sınıf kendi private bölümündeki öğeleri, bir global işleve, bir sınıfın bir üye işlevine ya da bir sınıfın tüm kodlarına açabiliyor. Sınıfımızın yalnızca belirli private öğelerine bir başka sınıfın erişebilmesini istiyor olalım. Bunun C++ dilinde doğrudan bir yolu yok. C++’ta arkadaşlık yalnızca sınıfın belirli öğeleri için sağlanamıyor. Eğer bir sınıfa arkadaşlık verirseniz sınıfınızın tüm private öğelerini o sınıfın erişimine açmış oluyorsunuz.  Yani ya hep ya hiç.

friend‘lik iki sınıf arasındaki bağlantıyı (coupling) arttırıyor. Sınıfınızın private bölümünde değişiklik yaptığınızda arkadaşlık verdiğiniz sınıfların kodlarında da değişiklik yapılması gerekiyor. Kodların birbirine bağlılığını azaltmak için sınıfın tüm private öğelerini erişime açmak yerine yalnızca bu ihtiyaca konu private öğeleri başka kod ya da kodların erişimine açmak daha iyi bir çözüm. Aşağıdaki gibi bir sınıfımız olsun:

OtherClass isimli bir sınıfa, sınıfımızın yalnızca private mx1 veri öğesine ve private pfunc üye işlevine erişim olanağı sağlamak istiyoruz. OtherClass sınıfı şöyle olsun:

Amacımızı gerçekleştirmenin birden fazla yolu olsa da en sık kullanılan yöntemlerden biri İngilizcede  Attorney Client olarak isimlendrilen idiyomu kullanmak. İdiyom basitçe şöyle:  OtherClass sınıfına doğrudan arkadaşlık vermek yerine -ki o zaman tüm private öğelerimizi OtherClass sınıfının erişimine açmış olurduk- kendi oluşturacağımız bir yardımcı sınıfa arkadaşlık vereceğiz. Arkadaşlık vereceğimiz sınıfın ismi Helper olsun. Yardımcı Helper sınıfı yalnızca static private işlevlere sahip olacak ve o da OtherClass sınıfına arkadaşlık verecek:

Artık, OtherClass sınıfı OurClass sınıfının private pfunc1 işlevine ve mx veri öğesine Helper sınıfının static private işlevlerine çağrı yaparak erişebilir:

Helper sınıfının amacı gerçekleştirmek için sunduğu private işlevlerin inline olarak tanımlandığını görüyorsunuz. OtherClass sınıfının private öğelerine erişim için Helper sınıfının private işlevlerine yaptığı çağrılar ciddi bir ek maliyet getirmeyecek.

Biraz da idiyoma verilen popüler isime değinelim: Avukat Müvekkil idiyomu. Buradaki yapı bir avukat ile müvekkili arasındaki ilişkiye benzemiyor mu? Bir avukat, temsil ettiği müvekkilinin tüm sırlarını bilir ancak bu sırların sadece bir kısmını başkalarıyla paylaşır. Örneğimizdeki Helper sınıfı avukat, OurClass sınıfı da müvekkil. Nasıl farklı işlerimiz için birden fazla avukat tutabiliyorsak, farklı farklı sınıflara sınıfımızın private bölümünün farklı kesimlerine erişim sağlamak için birden fazla yardımcı sınıf da oluşturabiliriz, değil mi?

Arkadaşlık bildirimleri türemiş sınıflar tarafından taban sınıflardan kalıtım yoluyla alınmıyorlar. Base sınıfı AttorneyBase sınıfına arkadaşlık vermiş olsun. Bu durumda AttorneyBase sınıfı Base sınıfının private bölümüne erişebilir. Der sınıfı da Base sınıfından public kalıtımı yoluyla elde edilmiş olsun. Bu durumda AttorneyBase sınıfı Der sınıfının private bölümüne erişemez. Ancak taban sınıf tarafından arkadaşlık verilen bir sınıf, taban sınıfın private bölümünde bildirilen bir sanal işlevi taban sınıf göstericisi ya da referansı ile çağırdığında, türemiş sınıfın ezen (override) işlevinin çalışma zamanında çalıştırılmasına bir engel yok. Aşağıdaki kodu inceleyin:

Share

Necati Ergin

C ve Sistem Programcıları Derneğinde eğitmen olarak çalışıyor.

Bunlar da ilginizi çekebilir

Kod Eklemek İçin Okuyun