Перезагрузка операторов +, -, ++ и --.
Создадим класс, над которым мы и будем ставить наши "Эксперименты". Очень хорошо для этого подойдет класс Money (деньги):
class Money
{
private int rub; //рубль
private int kop; //копейка
public Money()
{
rub = 0;
kop = 0;
}
public Money(int r, int k)
{
rub = r;
kop = k % 100;
}
public void howmuch()
{
Console.WriteLine("У вас " + rub + " рублей " + kop + " копеек");
}
}
Вот наш класс, который содержит 2 скрытых поля: rub и kop. Данный класс имеет 2 конструктора. Первый конструктор присваивает полям нулевые значения, а второй инициализирует их начальными значениями. Запись %100 означает остаток от деления на 100. С помощью такой записи мы защищаем себя от ввода заведомо ложного значения (напомню, что в рубле 100 копеек). Можно было написать защиту и получше, но сейчас мы не будем тратить на это время.
А сейчас еще один пример, того, как можно было бы использовать данный класс:
Money m1 = new Money(1, 50);
Money m2 = new Money(1, 50);
Money m3 = m1 + m2;
m3.howmuch();
Было бы логично, чтобы данная программа вывела, что у нас 3 рубля 0 копеек, но пока она такого сделать не может, т.к. понятия не имеет, как складывать деньги, т.е. не умеет пользоваться оператором +. Но мы то с вами умеем, поэтому давайте ее научим:
public static Money operator +(Money m1, Money m2)
{
Money tmp = new Money();
tmp.rub = m1.rub + m2.rub;
tmp.rub += (int)((m1.kop + m2.kop) / 100);
tmp.kop = (m1.kop + m2.kop) % 100;
return tmp;
}
Этот метод нужно вставить в наш класс Money. Здесь мы встречаемся с новым ключевым словом - operator. Обратите внимание, что наш перегруженный метод возвращает объект типа Money. Это позволяет нам писать выражения типа:
m4 = m1 + m2 + m3 + ... + mN;
Давайте поясним что же происходит в перегруженном методе. Сперва мы создаем объект tmp. Поскольку он создается с помощью конструктора по умолчанию, то и рубли и копейки в нем равны нулю. В следующей строке мы складываем рубли. А дальше весьма интересная конструкция. Просто сложить рубли не достаточно, нужно учесть тот факт, что при сложении копеек их может оказаться больше 100. Поэтому в следующей строке мы выполняем следующее:
а) складываем копейки
б) делим их на 100
в) с помощью приведения типов отбрасываем дробную часть
г) добавляем получившийся результат к рублям
Можно было написать и по-другому, например, так:
if ((m1.kop + m2.kop) >= 100) tmp.rub++;
Ну а дальше мы складываем копейки. И, наконец, возвращаем наш объект. После чего можно смело складывать наши денежки в одну кучу.
Ну а теперь научим наш класс вычитать денежки (это немного сложнее, т.к. нужно учитывать тот факт, что деньги не могут быть отрицательной величиной):
public static Money operator -(Money m1, Money m2)
{
Money tmp = new Money();
tmp.rub = m1.rub - m2.rub;
tmp.kop = m1.kop - m2.kop;
if (tmp.kop < 0) tmp.rub--;
tmp.kop = Math.Abs(tmp.kop);
if (tmp.rub < 0)
{
tmp.rub = 0;
tmp.kop = 0;
}
return tmp;
}
Вот и все. Выглядит достаточно сложно, но зато пользоваться очень удобно. Нам встретился метод Math.Abs, с помощью такой конструкции мы вызываем метод Abs, который находится в пространстве имен Math. Метод Abs - возвращает абсолютное значение (т.е. модуль числа). В конце работы нашего перегруженного оператора - мы проверяем поле rub, если оно оказалось отрицательным, то это означает, что второй операнд больше первого, поэтому возвращаем нули. Надеюсь, что вы разберетесь, как это "чудо" работает.
Ну и напоследок, хотелось бы рассказать про перегрузку операторов ++ и --. В отличие от операторов + и - эти операции являются унарными, т.е. применимы только к одному объекту. Давайте договоримся, что конструкция m1++ (где m1 - экземпляр класса Money) будет добавлять один рубль, а конструкция m1-- вычитать рубль. Если у нас меньше одного рубля, то операция -- обнулит поля rub и kop. Итак, приступим к реализации:
public static Money operator ++(Money m1)
{
m1.rub++;
return m1;
}
public static Money operator --(Money m1)
{
if (m1.rub == 0)
{
m1.rub = 0;
m1.kop = 0;
}
else
{
m1.rub--;
}
return m1;
}
После этого вы можете смело писать:
Money m1 = new Money(1, 60);
m1--;
m1.howmuch();
На экран будет выведено, что у вас 0 рублей 60 копеек.