Przeciążanie operatorów lub inaczej przeładowanie operatorów (z ang. operator overloading) to technika pozwalająca na definiowanie metod które wykonywane zostaną przy użyciu operatora. Na użycie tego mechanizmu mogą sobie pozwolić programujący w takich językach jak C++, C#, Perl czy Python. Dialekty Pascala takie jak Free Pascal oraz Delphi również pozwalają na stosowanie przeciążenia operatorów.
Przeciążanie operatorów w Free Pascalu
(Poniższa część artykułu dotyczy tylko dialektu Free Pascal !)
Operator przypisania
Aby przeładować operator przypisania należy użyć konstrukcji:
operator := (IDWartosci : TypWartosci) IDWyniku : TypWyniku; begin //Instrukcje wykonywane przy przypisaniu end;
Gdzie:
- IDWartosci to identyfikator (dowolny) prawego argumentu operatora przypisania (za pomocą którego możemy odwołać się do przypisywanej wartości)
- TypWarosci to typ przypisywanej wartości
- IDWyniku to identyfikator (dowolny) pod jakim figuruje wartość zwracana przez operator przypisania
- TypWyniku to typ zwracanej wartości
Przykład:
uses SysUtils; operator := (Wartosc : String) Wynik : integer; begin Wynik := StrToInt(Wartosc); //Konwersacja łańcucha znaków na liczbę całkowitą end; var n : integer; s : string; begin s := '777'; n := s; WriteLn(n); end.
Kod z powyższego przykładu powoduje wywołanie funkcji StrToInt (konwertującej łańcuch znaków Wartosc na liczbę całkowitą, o ile to możliwe) podczas próby przypisania ciągu znaków do zmiennej typu liczbowego, całkowitego. Bez przeciążenia operatora próba wykonania takiej operacji skończyła by się błędem podczas kompilacji źródła.
Inne przykłady:
type
TOsoba = record
Imie : string;
Nazwisko : string;
Zawod : string;
end;
operator := (Wartosc : array of string) Wynik : TOsoba;
begin
with Wynik do
begin
Imie := Wartosc[0];
Nazwisko := Wartosc[1];
Zawod := Wartosc[2];
end;
end;
var
OsobaFoo : array[0..2] of string = ('Jan', 'Kowalski', 'Teleinformatyk');
OsobaBar : TOsoba;
begin
OsobaBar := OsobaFoo;
with OsobaBar do
begin
WriteLn(imie);
WriteLn(Nazwisko);
WriteLn(Zawod);
end;
end.
type TNumber = record Lo : integer; Hi : integer; end; operator := (Wartosc : word) Wynik : TNumber; begin Wynik.Lo := Lo(Wartosc); Wynik.Hi := Hi(Wartosc); end; var MyNumber : TNumber; begin MyNumber := 65535; WriteLn(MyNumber.Lo); WriteLn(MyNumber.HI); WriteLn; end.
Operatory arytmetyczne
Przeciążenie operatorów arytmetycznych wymaga podania dwóch parametrów wraz z ich typami w deklaracji. Pierwszy parametr odpowiada lewej stronie wyrażenia, drugi stronie prawej.
Ogólny schemat:
operator Opr_artm (WLewa : TypL; WPrawa : TypP;) IDWynik : TypWynik; begin //Instrukcje end;
Gdzie:
- Opr_artm to przeciążany operator arytmetyczny
- WLewa to identyfikator reprezentujący wartość lewej strony wyrażenia np. 2 + 3
- WPrawa to identyfikator reprezentujący wartość prawej strony wyrazenia np. 2 + 3
- TypL to typ identyfikatora lewej strony wyrażenia
- TypP to typ identyfikatora prawej strony wyrażenia
- IDWynik to identyfikator pod jakim figuruje wartość zwracana przez operator przypisania
- TypWynik to typ zwracany w wyniku działania
Operatory logiczne
Przeładowanie operatorów logicznych również wymaga podania dwóch argumentów, podobnie jak przeładowanie operatorów arytmetycznych, reprezentujących obie strony wyrażenia. Dozwolone jest przeciążanie wszystkich operatorów logicznych oprócz operatora różności “<>”. Wartość zwracana przez wyrażenie z operatorem różności jest negacją równości tego wyrażenia. Ponadto wynik przeciążenia operatora logicznego musi być typu boolean.
Szkielet deklaracji:
operator Opr_log (WLewa : TypL, WPrawa : TypP) Wynik : boolean; begin //Instrukcje end;
Gdzie:
- Opr_log to przeciążany operator logiczny
- WLewa, WPrawa to kolejno lewa i prawa to identyfikatory reprezentujące lewa i prawą stronę wyrażenia logicznegi
- TypL, TypP to typy porównywanych wartości
Przykład:
type
TNumber = record
Lo, Hi : integer;
end;
operator := (Wartosc : LongInt) Wynik : TNumber;
begin
Wynik.Lo := Lo(Wartosc);
Wynik.Hi := Hi(Wartosc);
end;
operator = (WLewa : integer; WPrawa : TNumber) Wynik : boolean;
begin
if (Lo(WLewa) = WPrawa.Lo ) and (Hi(WLewa) = WPrawa.Hi) then
Wynik := true else Wynik := false;
end;
operator > (WLewa : integer; WPrawa : TNumber) Wynik : boolean;
begin
Wynik := false;
if (Hi(WLewa) > WPrawa.Hi) then
Wynik := true
else
if (Lo(WLewa) > WPrawa.Lo) then
Wynik := true;
end;
operator < (WLewa : integer; WPrawa : TNumber) Wynik : boolean;
begin
Wynik := false;
if (Hi(WLewa) < WPrawa.Hi) then
Wynik := true
else
if (Lo(WLewa) < WPrawa.Lo) then
Wynik := true;
end;
var
foo : TNumber;
bar : integer;
begin
Foo := 100;
WriteLn('Foo równe 100'#10#13'Podaj wartosc bar');
ReadLn(Bar);
if bar = foo then
WriteLn('Bar = Foo')
else
if bar > foo then
WriteLn('Bar > Foo')
else
if bar < foo then
WriteLn('Bar < Foo')
else
WriteLn('Bar <> Foo');
end.
Kod programu z powyższego przykładu przeciąża operator “=”,”>”,”<” (oraz “:=”) dla nowego typu TNumber (typ przechowuje liczbę rozdzieloną na mniej i bardziej znaczącą połówkę, z punktu widzenia systemu binarnego). Przy użyciu przeciążonego operatora, następuje porównanie kolejnych połówek liczby podanej jako wartość lewostronną wyrażenia (poprzez funkcje Lo i Hi), oraz połówek przechowywanych w rekordzie TNumber;
Więcej o przeciążaniu operatorów w FreePascalu:
Free Pascal Language Referance Guide s. 116

0 Odpowiedzi do “Przeciążenie operatorów”