C# PRZEŁADOWANIE OPERATORÓW


Tą lekcję poświęcimy na omówienie przeładowania operatorów, jak pamiętasz pisaliśmy już o przeładowaniu, tyle że metod. Przeładowanie operatorów to potężny mechanizm, możesz przeładowywać wszystkie operatory: arytmetyczne, porównań, []… itp. Co nam daje przeładowanie operatorów, otóż możemy dokładnie określić jak ma się zachowywać wywołanie np. + przy naszym obiekcie. Rozróżniamy operatory jednoargumentowe oraz dwuargumentowe. Ogólna deklaracja przeładowania operatorów dwuargumentowych wygląda następująco:

specyfikator_dostępu static typ_zwracany operator typ_operatora(typ_parametru1 nazwa_parametru1, typ_parametru2 nazwa_paramteru2)
{

}

Należy pamiętać o tym, że przynajmniej jeden z parametrów musi być tego samego typu jak klasa, przy przeładowywaniu operatora jednoargumentowego typ parametru musi być taki sam jak klasa, w której się znajduje.

O.K przechodzimy do przykładu w którym to ukazane jest działanie przeładowania operatorów. Nasza klasa w której zaimplementujemy przeładowanie będzie trochę militarna, otóż będziemy operować dywizjami, poczym za pomocą operatora + będziemy mogli dodawać do jednej dywizji takie parametry jak siła do drugiej.

Początek kodu:

using System;

class Dywizja
{
public int czolgi;
public double amunicja;
public int zolnierze;
public double ropa;
public int samoloty;
public int lodzie;


public Dywizja(int czolg, double ammo, int soldat, double paliwo, int lotnictwo, int lodzie)
{
czolgi = czolg;
amunicja = ammo;
zolnierze = soldat;
ropa = paliwo;
samoloty = lotnictwo;
this.lodzie = lodzie;
}


public Dywizja()
{
czolgi = 0;
amunicja = 0;
zolnierze = 0;
ropa = 0;
samoloty = 0;
lodzie = 0;
}


public static Dywizja operator +(Dywizja D1, Dywizja D2)
{
Dywizja wynik = new Dywizja();
wynik.czolgi = D1.czolgi + D2.czolgi;
wynik.amunicja = D1.amunicja + D2.amunicja;
wynik.zolnierze = D1.zolnierze + D2.zolnierze;
wynik.ropa = D1.ropa + D2.ropa;
wynik.samoloty = D1.samoloty + D2.samoloty;
wynik.lodzie = D1.lodzie + D2.lodzie;


return wynik;
}


public void Dane_dywizji(){
Console.WriteLine(„Czołgi = ” + czolgi);
Console.WriteLine(„Amunicja = ” + amunicja);
Console.WriteLine(„Zołnierze = ” + zolnierze);
Console.WriteLine(„Ropa = ” + ropa);
Console.WriteLine(„Samoloty = ” + samoloty);
Console.WriteLine(„Łodzie = ” + lodzie);
Console.WriteLine(„\n\n”);
}


}


class Pokaz
{
public static void Main()
{
Dywizja DPanc_Gertruda = new Dywizja(70, 148.94, 24, 307.76, 0, 3);
Dywizja DPiech_Sapiechy = new Dywizja(2, 70.32, 179, 15.00, 0, 1);


Console.WriteLine(„Dywizna Pancera, generała Gertruda posiada stan:”);
DPanc_Gertruda.Dane_dywizji();


Console.WriteLine(„Dywizna Piechoty, porucznika Sapiechy posiada stan:”);
DPiech_Sapiechy.Dane_dywizji();


Console.WriteLine(„Połączono Dywizję generała Gertruda i Dywizję porucznika Sapiechy\nw połączoną dywizję uderzeniową\n”);


Dywizja Polaczona_dywizja = DPanc_Gertruda + DPiech_Sapiechy;
Console.WriteLine(„Połączona Dywizja uderzeniowa posiada stan:”);
Polaczona_dywizja.Dane_dywizji();
}

}

Koniec kodu:

O.K co my tu mamy. A więc tworzymy klasę Dywizja, która to przechowuje takie dane jak ilość czołgów czy galony ropy, mamy również metodę która wyświetla wartości składników klasy. Posiada również przeładowany operator +, typ zwracany jest taki jak klasa, gdyż operator + posłuży nam do łączenia Dywizji. Jako parametr pobieramy dwa obiekty klasy Dywizja. Kod wewnątrz przeładowanego operatora jest ci zrozumiały. Tak samo nie powinno być problemu z przyswojeniem kodu w klasie Pokaz.

Czy musisz za każdym zwracać jakąś wartość? Otóż nie, możesz przecież użyć operatora do dowolnego celu, możesz np. za jego pomocą dodawać elementy do tablic, ale nic nie zwracać, no bo po co? Mogliśmy zamiast drugiego operatora typu Dywizja użyć operatora np. typu int, no ale nie takie zadanie miał spełniać nasz operator. Jak widzisz jest to bardzo potężny mechanizm. Dobrze jest aby przeładowane operatory spełniały podobne funkcje do jakich pierwotnie służyły, czyli dobrze jest aby przeładowanie operatory porównań zwracały wartość bool oraz porównywały dwa operatory. Teraz szybciutko omówimy operator jednoargumentowy. Jaki to operator? Pamiętasz lekcję o inkrementacji, czyli nasz ++, trudno znaleźć dla niego zastosowanie w naszym programie, ale operator dekrementacji może się przydać, jak wiesz zmniejsza on z założenia wartość zmiennej o 1, teraz też tak uczynimy, dodamy operator dekrementacji byś bez problemu ocenił działanie przeładowanie operatorów jednoargumentowych, pamiętaj o tym, że parametr pobierany podczas przeładowania operatora jednoargumentowego, musi być takiego samego typu jak klasa w której się znajduje przeładowanie. A oto nasz program z dodanym jeszcze jednym przeładowaniem, tym razem jest to operator jednoargumentowy:

Początek kodu:

using System;


class Dywizja
{
public int czolgi;
public double amunicja;
public int zolnierze;
public double ropa;
public int samoloty;
public int lodzie;


public Dywizja(int czolg, double ammo, int soldat, double paliwo, int lotnictwo, int lodzie)
{
czolgi = czolg;
amunicja = ammo;
zolnierze = soldat;
ropa = paliwo;
samoloty = lotnictwo;
this.lodzie = lodzie;
}


public Dywizja()
{
czolgi = 0;
amunicja = 0;
zolnierze = 0;
ropa = 0;
samoloty = 0;
lodzie = 0;
}


public static Dywizja operator +(Dywizja D1, Dywizja D2)
{
Dywizja wynik = new Dywizja();
wynik.czolgi = D1.czolgi + D2.czolgi;
wynik.amunicja = D1.amunicja + D2.amunicja;
wynik.zolnierze = D1.zolnierze + D2.zolnierze;
wynik.ropa = D1.ropa + D2.ropa;
wynik.samoloty = D1.samoloty + D2.samoloty;
wynik.lodzie = D1.lodzie + D2.lodzie;
return wynik;
}

public static Dywizja operator –(Dywizja D1)
{
Dywizja wynik = new Dywizja();
wynik.czolgi = D1.czolgi- 1;
wynik.amunicja = D1.amunicja-1;
wynik.zolnierze = D1.zolnierze-1;
wynik.ropa = D1.ropa-1;
wynik.samoloty = D1.samoloty-1;
wynik.lodzie = D1.lodzie-1;
return wynik;
}

public void Dane_dywizji(){
Console.WriteLine(„Czołgi = ” + czolgi);
Console.WriteLine(„Amunicja = ” + amunicja);
Console.WriteLine(„Zołnierze = ” + zolnierze);
Console.WriteLine(„Ropa = ” + ropa);
Console.WriteLine(„Samoloty = ” + samoloty);
Console.WriteLine(„Łodzie = ” + lodzie);
Console.WriteLine(„\n\n”);
}

}


class Pokaz
{
public static void Main()
{
Dywizja DPanc_Gertruda = new Dywizja(70, 148.94, 24, 307.76, 0, 3);
Dywizja DPiech_Sapiechy = new Dywizja(2, 70.32, 179, 15.00, 0, 1);


{        Dywizja DPanc_Gertruda = new Dywizja(70, 148.94, 24, 307.76, 0, 3);        Dywizja DPiech_Sapiechy = new Dywizja(2, 70.32, 179, 15.00, 0, 1);


Console.WriteLine(„Dywizna Pancera, generała Gertruda posiada stan:”);
DPanc_Gertruda.Dane_dywizji();


Console.WriteLine(„Dywizna Piechoty, porucznika Sapiechy posiada stan:”);
DPiech_Sapiechy.Dane_dywizji();


Console.WriteLine(„Połączono Dywizję generała Gertruda i Dywizję porucznika Sapiechy\nw połączoną dywizję uderzeniową\n”);


Dywizja Polaczona_dywizja = DPanc_Gertruda + DPiech_Sapiechy;
Console.WriteLine(„Połączona Dywizja uderzeniowa posiada stan:”);
Polaczona_dywizja.Dane_dywizji();


Console.WriteLine(„Połączona Dywizja uderzeniowa posiada po degradacji stan:”);
Polaczona_dywizja–;
Polaczona_dywizja.Dane_dywizji();
}

}

Koniec kodu:

Ok. dla ciebie to już wszystko jasne, jedyną jakąś nie jasnością może być to, że w konstruktorze klasy Dywizja użyliśmy słowa kluczowego this, gdyż pobieraliśmy parametr o takiej samej nazwie, dzięki this mieliśmy dostęp do zmiennej składowej klasy, a nie parametru metody, dzięki temu nie trzeba było zmieniać nazwy parametru.

Jeszcze jedną ważną rzeczą jest to że podczas przeładowania operatorów ma znaczenie kolejność parametrów, co to oznacza, otóż to:
public static Dywizja operator +(Dywizja D1, int x)
{

}

Nie jest tym samym:
public static Dywizja operator +(int x,Dywizja D1)
{

}

Jest to ważne i należy o tym pamiętać, zawsze przeładowywać operatory dla dwóch przypadków.