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”



    1. Nie ma jeszcze komentarzy

    Dodaj komentarz