Konuya Giriş:
Perl 5'in ilk sürümünden itibaren dil, referansları bir paketle ilişkilendirme mekanizması (blessing) aracılığıyla temel bir nesne modelini desteklemektedir. Perl'de nesneler, bless fonksiyonu ile "kutsanan" normal referanslardır (hash, array veya scalar), bu da sistemin yöntemleri paket (namespace) aracılığıyla bulmasını sağlar.
Sorun:
Kutsanmamış referanslar, normal veri yapıları olmaya devam eder ve bunlar üzerinde bir yöntem çağrılmaya çalışılması, çalışma zamanında hatalara yol açar. Programcının referansın türüne yeterince dikkat etmemesi, nesnenin iç kısımlarını yanlışlıkla manipüle etme riskini taşır ve kapsüllemeyi ihlal eder. Ayrıca, kontrol olmaksızın "ham" dereference işlemi {} veya @{} kullanmak, zor tespit edilen hatalara yol açar.
Çözüm:
Nesneleri yalnızca bless ile doğru bir şekilde oluşturmak, ardından nesne verilerine yalnızca dereference ile erişmek ve Scalar::Util modülü ile tür kontrolü yapmak (ref, blessed) gerekir. Daima yapıların doğrudan erişiminden (örneğin, $obj->{key}) kaçınılmalı ve kontrol sağlamak için aksesörler (getter/setter) uygulanmalıdır.
Kod örneği:
package Animal; sub new { my $class = shift; my $self = { name => shift }; bless $self, $class; return $self; } sub name { my $self = shift; $self->{name} = shift if @_; return $self->{name}; } my $dog = Animal->new("Rex"); print $dog->name; # aksesör aracılığıyla güvenli print $dog->{name}; # doğrudan erişim, önerilmez
Anahtar özellikler:
blessed veya ref kullanmak hataların sayısını önemli ölçüde azaltırSadece bir hash referansı, bless olmadan nesne olarak kullanılabilir mi?
Hayır, bless çağrısı olmadan referansın paketle bir ilişkisi yoktur ve Perl yöntemleri bulamayacaktır ("Can't call method" hatası), iç yapısı aynı olsa bile.
Bir değişkenin gerçekten nesne olup olmadığını güvenli bir şekilde nasıl belirleyebilirim?
Referansın kutsanıp kutsanmadığını kontrol etmek için Scalar::Util::blessed($obj) fonksiyonunu kullanmalısınız. Yalnızca kutsanmış referanslar nesne olarak kabul edilir.
use Scalar::Util 'blessed'; my $obj = {}; print blessed($obj) ? 'yes' : 'no'; # 'no' yazdırır
Hatalı bir nesne üzerinde yöntem çağrısı yapılabilir mi?
Kutsanmamış bir referans üzerinde yöntem çağrısı yapmak, ani bir hata oluşturur: Perl, referansın kendi paketini bilmesini bekler. AUTOLOAD mekanizmaları ve dinamik yüklemeler hariç, ancak bu bir anti-pattern olup hatalara yol açar.
Genç bir geliştirici, $person = {name => 'Vasya'} yapısını elle oluşturur ve bless çağrısını unutur, ardından $person->name() çağrısı yapmaya çalıştığında runtime hatası ile karşılaşır.
Artılar:
Eksiler:
Koddaki her nesne oluştururken bless çağrılıyor ve verilere yalnızca name() yöntemiyle erişiliyor. blessed() ile kontrol, yöntemlerin çalıştırılmasından önce hataların işlenmesini sağlar.
Artılar:
Eksiler: