Operatör aşırı yüklemesi - Operator overloading
polimorfizm |
---|
Ad hoc polimorfizm |
parametrik polimorfizm |
alt tipleme |
Gelen bilgisayar programlama , operatör aşırı yüklenmesi , bazen adlandırılan operatör ad hoc polymorphism , belirli bir durumdur polimorfizm farklı, operatörler kendi argümanları bağlı olarak farklı uygulamalar var. Operatör aşırı yüklemesi genellikle bir programlama dili , bir programcı veya her ikisi tarafından tanımlanır .
Gerekçe
Operatör aşırı yüklemesi sözdizimsel şekerdir ve hedef etki alanına daha yakın gösterim kullanarak programlamaya izin verdiği ve kullanıcı tanımlı türlere bir dilde yerleşik türlerle benzer düzeyde sözdizimsel destek sağladığı için kullanılır. Örneğin, matematiksel nesnelerin bilgisayar gösterimlerinin kağıt üzerinde olduğu gibi aynı sözdizimi ile manipüle edilmesine izin verdiği bilimsel hesaplamada yaygındır.
Operatör aşırı yüklemesi, işlev çağrıları kullanılarak taklit edilebileceğinden, bir dilin (işlevlerle birlikte) ifade gücünü değiştirmez . Örneğin, değişkenlerin dikkate a
, b
ve c
bir kullanıcı tanımlı tür gibi matrisler :
a + b * c
Operatör aşırı yüklemesini destekleyen bir dilde ve '*' operatörünün '+' operatöründen daha yüksek önceliğe sahip olduğu genel varsayımıyla , bu kısa bir yazma şeklidir:
Add(a, Multiply(b, c))
Ancak, eski sözdizimi yaygın matematiksel kullanımı yansıtır.
Örnekler
Bu durumda, ek operatör kullanıcı tanımlı bir türüne ilave edilmesine olanak sağlamak üzere aşırı Time
olarak C ++ :
Time operator+(const Time& lhs, const Time& rhs) {
Time temp = lhs;
temp.seconds += rhs.seconds;
temp.minutes += temp.seconds / 60;
temp.seconds %= 60;
temp.minutes += rhs.minutes;
temp.hours += temp.minutes / 60;
temp.minutes %= 60;
temp.hours += rhs.hours;
return temp;
}
Toplama ikili bir işlemdir , yani iki işleneni vardır . C++'da iletilen argümanlar işlenenlerdir ve temp
nesne döndürülen değerdir.
İşlem lhs
, gizli this
argümanla değiştirilerek bir sınıf yöntemi olarak da tanımlanabilir ; Ancak bu, sol işleneni şu türden olmaya zorlar Time
:
// The "const" right before the opening curly brace means that |this| is not modified.
Time Time::operator+(const Time& rhs) const {
Time temp = *this; // |this| should not be modified, so make a copy.
temp.seconds += rhs.seconds;
temp.minutes += temp.seconds / 60;
temp.seconds %= 60;
temp.minutes += rhs.minutes;
temp.hours += temp.minutes / 60;
temp.minutes %= 60;
temp.hours += rhs.hours;
return temp;
}
Bir Not tekli bir Sınıf yöntemi olarak tanımlanan operatörü (sadece çalışır belirgin bir bağımsız değişken almak olur this
):
bool Time::operator!() const {
return hours == 0 && minutes == 0 && seconds == 0;
}
Küçüktür (<) operatörü, bir yapıyı veya sınıfı sıralamak için genellikle aşırı yüklenir:
class Pair {
public:
bool operator<(const Pair& p) const {
if (x_ == p.x_) {
return y_ < p.y_;
}
return x_ < p.x_;
}
private:
int x_;
int y_;
};
Önceki örneklerde olduğu gibi, son örnekte sınıf içinde operatör aşırı yüklemesi yapılır. C++'da, küçüktür işlecini (<) aşırı yükledikten sonra, bazı sınıfları sıralamak için standart sıralama işlevleri kullanılabilir.
eleştiriler
Operatör aşırı yüklemesi, programcıların işlenenlerin türlerine bağlı olarak operatörlerin anlamlarını yeniden atamalarına izin verdiği için sıklıkla eleştirilmiştir. Örneğin, kullanımı <<
operatörün C ++ değişken bit değiştirir bıraktığı takdirde bit ve bir tamsayıdır tiptedir, fakat eğer bir çıkış akışı daha sonra yukarıdaki kod bilgileri dener akışına. Operatör aşırı yüklemesi, orijinal programcının bir operatörün olağan semantiğini değiştirmesine ve sonraki programcıları sürpriz bir şekilde yakalamasına izin verdiği için, operatör aşırı yüklemesini dikkatli kullanmak iyi bir uygulama olarak kabul edilir ( Java'nın yaratıcıları, zorunlu olmasa da bu özelliği kullanmamaya karar verdiler). bu yüzden).
a << b
a
b
a
b
a
b
Operatörlerle ilgili daha incelikli bir başka konu, matematikteki belirli kuralların yanlışlıkla beklenebileceği veya istemeden varsayılabileceğidir. Örneğin, + (yani )' nin değiştirilebilirliğia + b == b + a
her zaman geçerli değildir; Bunun bir örneği, işlenenler dizgeler olduğunda ortaya çıkar, çünkü + genellikle dizgelerin birleştirilmesini gerçekleştirmek için aşırı yüklenir (yani, "bird" + "song"
verimler "birdsong"
iken "song" + "bird"
verimler "songbird"
). Bu argümana tipik bir karşı koyma doğrudan matematikten gelir: + tamsayılarda (ve daha genel olarak herhangi bir karmaşık sayı) değişmeli iken, diğer değişken "tipleri" için değişmeli değildir. Pratikte +, örneğin yuvarlama hataları nedeniyle kayan noktalı değerlerle her zaman ilişkisel değildir . Başka bir örnek: Matematikte çarpma, gerçek ve karmaşık sayılar için değişmeli, ancak matris çarpmasında değişmeli değil .
Katalog
Bazı yaygın programlama dillerinin bir sınıflandırması, operatörlerinin programcı tarafından aşırı yüklenebilir olup olmamasına ve operatörlerin önceden tanımlanmış bir kümeyle sınırlı olup olmamasına göre yapılır.
operatörler | Aşırı yüklenemez | Aşırı yüklenebilir |
---|---|---|
Yeni tanımlanabilir | ||
Sınırlı set |
Operatör aşırı yüklemesinin zaman çizelgesi
1960'lar
Algol 68 spesifikasyon operatör aşırı yüklenmesini izin verdi.
Aşırı yüklenmiş ¬, =, ≠ ve abs operatörlerinin tanımlandığı ALGOL 68 dil özelliğinden (sayfa 177) alıntı :
10.2.2. Operations on Boolean Operands a) op ∨ = (bool a, b) bool:( a | true | b ); b) op ∧ = (bool a, b) bool: ( a | b | false ); c) op ¬ = (bool a) bool: ( a | false | true ); d) op = = (bool a, b) bool:( a∧b ) ∨ ( ¬b∧¬a ); e) op ≠ = (bool a, b) bool: ¬(a=b); f) op abs = (bool a)int: ( a | 1 | 0 );
Bir operatörü aşırı yüklemek için özel bir bildirime gerek olmadığını ve programcının yeni operatörler oluşturmakta özgür olduğunu unutmayın.
1980'ler
Ada , Ada 83 dil standardının yayınlanmasıyla, başlangıcından itibaren operatörlerin aşırı yüklenmesini destekler. Ancak, dil tasarımcıları yeni operatörlerin tanımını engellemeyi seçtiler. "+", "*", "&" gibi tanımlayıcılarla yeni işlevler tanımlanarak yalnızca dilde mevcut operatörler aşırı yüklenebilir. Dilin sonraki revizyonları (1995 ve 2005'te) mevcut operatörlerin aşırı yüklenmesine ilişkin kısıtlamayı korur .
Olarak C ++ , operatör yükleme daha daha rafine edilir ALGOL 68 .
1990'lar
Sun Microsystems'deki Java dili tasarımcıları aşırı yüklemeyi atlamayı seçti.
Ruby , basit yöntem çağrıları için sözdizimsel şeker olarak operatörün aşırı yüklenmesine izin verir.
Lua , ilk işlenen bu operatörü tanımlamıyorsa, ikinci işlenen için yöntemin kullanılacağını ek özelliği ile yöntem çağrıları için sözdizimsel şeker olarak operatörün aşırı yüklenmesine izin verir.
2000'ler
Microsoft , 2001'de C# 'a ve 2003'te Visual Basic .NET'e operatör aşırı yüklemesini ekledi .
Scala , tüm operatörleri yöntem olarak ele alır ve bu nedenle proxy tarafından operatörün aşırı yüklenmesine izin verir.
Gelen Raku , bütün operatörlerin tanımı sözcük işlevlerine atanır ve bu nedenle, işlev tanımları kullanılarak, operatörler aşırı olabilir ya da yeni operatörler ilave edildi. Örneğin, bir Date nesnesini "+" ile artırmak için Rakudo kaynağında tanımlanan işlev :
multi infix:<+>(Date:D $d, Int:D $x) {
Date.new-from-daycount($d.daycount + $x)
}
"Çoklu" kullanıldığından, işlev çoklu gönderim adayları listesine eklenir ve "+" yalnızca işlev imzasındaki tür kısıtlamalarının karşılandığı durumda aşırı yüklenir. Aşırı yükleme kapasitesi + , * , >= , postfix ve i terimini vb. içerirken , çeşitli ayraç operatörlerinin aşırı yüklenmesine de izin verir: " [ x, y ] ", "x [ y ] ", "x { y } " ve "x ( y ) ".
Kotlin , kuruluşundan bu yana operatör aşırı yüklemesini destekledi.
Ayrıca bakınız
- İşlev aşırı yüklemesi
- Polimorfizm (bilgisayar bilimi)
- alt program
- Operatör (programlama)
- C ve C++ operatörleri
- mutatör yöntemi
- Dizin oluşturucu (programlama)
- Özellik (programlama)