D/Przeładowywanie operatorów
Wstęp
edytujPrzeładowywanie operatorów polega na zdefiniowaniu oczekiwanego zachowania dla zwykłych operatorów +, -, *, >> itd. Dzięki temu możemy napisać klasę obsługującą macierze (tablice dwuwymiarowe) z wygodnymi operacjami arytmetycznymi zarówno względem pojedynczych liczb (przeprowadzenie operacji na każdej komórce i podanej liczbie) jak i względem innych macierz, poprzez np. pomnożenie odpowiadających sobie komórek. Innym przykładem może być operator - do odwracania kąta w formacie stopnie-minuty-sekundy.
Operatory jednoargumentowe
edytujMożemy przeładować łącznie 6 operatorów jednoargumentowych.
Operator | Faktyczny zapis |
---|---|
-e | e.opUnary!("-")() |
+e | e.opUnary!("+")() |
~e | e.opUnary!("~")() |
*e | e.opUnary!("*")() |
++e | e.opUnary!("++")() |
--e | e.opUnary!("--")() |
Wspomniany we wstępie przykład z kątem (pomińmy fakt kątów ujemnych):
import std.stdio;
import std.format;
class coord
{
private:
/* Kolejno stopnie, minuty i sekundy */
int degrees;
int minutes;
int seconds;
public:
this(int degrees, int minutes, int seconds)
{
this.degrees = degrees;
this.minutes = minutes;
this.seconds = seconds;
}
/* Próba wypisania danych */
void toString(scope void delegate(const(char)[]) sink) const
{
writef("[%d, %d, %d]", degrees, minutes, seconds);
}
auto opUnary(string s)() if (s == "-")
{
return new coord(-degrees, -minutes, -seconds);
}
}
void main()
{
auto c = new coord(-20, 5, -12);
writefln("%s", c);
writefln("%s", -c);
}
Stdout:
[-20, 5, -12] [20, -5, 12]
Jeśli nie rozumiesz fragmentu o wypisywaniu danych odsyłam tu.
Postinkrementacja i postdekrementacja
edytujD nie pozwala na przeładowanie e-- i e++, więc w przypadku obiektów trzeba posługiwać się predekrementacją i preinkrementacją.
Operatory rzutowania
edytujOperatorów rzutowania może być tyle na ile typów chcielibyśmy rzutować, więc w praktyce mamy do czynienia z tylko jednym sposobem:
Operator | Faktyczny zapis |
---|---|
cast(typ) e | e.opCast!(typ)() |
Przykładem takiego rzutowania może być klasa sprawdzająca czy string wskazuje na prawdę, tj. 't' i 'T' (od true) to prawda, wszystko inne – fałsz.
import std.stdio;
import std.format;
/* Wspomniana klasa */
class isTrue
{
private:
/* String na później */
string str;
public:
/* Konstruktor */
this(string str)
{
this.str = str;
}
/* Operator rzutowania */
bool opCast()
{
return (str == "y" || str == "Y");
}
}
void main()
{
/* Tablica obiektów klasy isTrue, sprawdzających *
* „prawdziwość” przypisanych stringów */
isTrue[] arr;
arr ~= new isTrue("y");
arr ~= new isTrue("a");
arr ~= new isTrue("tralala");
arr ~= new isTrue("Y");
arr ~= new isTrue("zupa");
/* Iteracja po całej tablicy */
foreach(isTrue a; arr)
writefln("%s", cast(bool) a); //Wypisanie elementów po rzutowaniu na bool
}
Stdout:
true false false true false
Czyli wszystko się zgadza
W przygotowaniu: Index / Slice unrary operators, 2 argumentowe operatory, operatory porównania |