Sorunun Tarihi:
Operatör aşırı yüklemesi (overloading) ve büyülü yöntemlerin kullanımı, Perl'in nesne soyutlamalarınızı, karmaşık türleri oluşturmak için son derece önemli olan ileri düzey yönlerinden biridir. Perl başlangıçta OOP ve aşırı yüklemeye odaklanmamıştı, ancak 5. sürümü ile nesnelerin standart davranışlarını pragma overload ve özel yöntemleri ekleyerek genişletmek mümkün hale geldi.
Problem:
Ana ince ayrıntı, mekanizmanın oldukça esnek olmasıdır, ancak hata yapma olasılığı yüksektir: aşırı yüklenmiş bir objenin davranışı her zaman sezgisel olmayabilir, hatalı aşırı yükleme sonsuz rekursiyona, istenmeyen dönüşümlere ve bağlam hatalarına yol açar. Hataların büyük bir kısmı, sayı ve dize aşırı yüklemelerinin karıştırılmasından, ayrıca tanımsız operatör yöntemlerine beklenmedik çağrılardan kaynaklanmaktadır.
Çözüm:
Gerekli operatörler için strikt bir pragma overload kullanın, nesnenin dönüşüm yollarını net bir şekilde tanımlayın, her iki bağlamda (sayısal ve dize) çalışmayı öngörün ve geri dönüşleri açıkça tanımlayın. Tüm beklenen operatörleri işlemek ve aşırı yüklemelerin mirasına dikkat etmek önerilir.
Kod örneği:
package MyNum; use overload '+' => 'add', '""' => 'as_string'; sub new { my ($class, $value) = @_; bless { val => $value }, $class; } sub add { my ($self, $other, $swap) = @_; my $sum = $self->{val} + (ref($other) ? $other->{val} : $other); return __PACKAGE__->new($sum); } sub as_string { my $self = shift; return $self->{val}; } 1; # Kullanım my $a = MyNum->new(5); my $b = MyNum->new(7); my $c = $a + $b; print "$c "; # 12
Anahtar Özellikler:
Tuzaklı Soru 1: Sadece dize bağlamında operatörleri aşırı yüklediğimde (""") sayısal karşılaştırma otomatik olarak çalışacak mı?
Hayır, sayısal dönüşümü (0+) açıkça tanımlamanız gerekir, aksi takdirde Perl dize yöntemine göre dönüştürmeye çalışır, bu her zaman beklenen sonuca yol açmaz (örneğin, eq/== için farklı davranış).
Tuzaklı Soru 2: Aşırı yüklenmiş bir nesne, pragma overload'da açıkça belirtilmeyen operatörleri destekler mi?
Hayır, sadece açıkça listelenenler desteklenir. Diğerleri temel davranışı kullanır veya hatalara neden olur.
Tuzaklı Soru 3: Aşırı yüklenmiş bir operatör basit bir skalar değer döndürebilir mi?
Döndürebilir, ancak bu durumda yöntem zinciri ve nesne özelliği kaybolur, bu da sonraki kodda hatalara yol açar: ya sonraki işlemler için aşırı yükleme çalışmayı durdurur ya da mantık hatasına yol açar.
Geliştirici, nesnesi için yalnızca "+" ve "" operatörlerini aşırı yükleyerek 0+, -, cmp’yi unuttu. "==" ile karşılaştırma yaparken hatalı sonuç aldı çünkü stringification tetiklendi ve gerekli dönüşüm yapılmadı.
Artıları:
Eksileri:
Geliştirici pragma overload kullanıyor ve gerekli tüm operatörleri kapsıyor (", 0+, +, -, x, <=>), uyumsuz olanlar için ise bilgilendirici bir hata ile istisna fırlatıyor.
Artıları:
Eksileri: