Чтение онлайн

ЖАНРЫ

Интернет-журнал "Домашняя лаборатория", 2007 №9
Шрифт:

/// </summary>

/// <param name="sum"> снимаемая сумма</param>

public void getMoney(int sum)

{

int res=2;

if(sum <= balance)debit += sum;

else res = -2;

balance;

Mes(res, sum);

}//getMoney

/// <summary>

/// вычисление баланса

/// </summary>

/// <returns>тeкyщий бaлaнc</returns>

int balance

{

return(credit — debit);

}

/// <summary>

/// Уведомление о выполнении операции

/// </summary>

void Mes(int result, int sum)

{

switch (result)

{

case 1:

Console.WriteLine("Операция

зачисления денег прошла успешно!");

Console.WriteLine("Сумма={0},

Ваш текущий баланс={1}", sum,balance);

break;

case 2:

Console.WriteLine("Операция снятия денег прошла успешно!");

Console.WriteLine("Сумма={0},

Ваш текущий баланс={1}", sum,balance);

break;

case -1:

Console.WriteLine("Операция зачисления денег не выполнена!");

Console.WriteLine("Сумма должна быть больше нуля!");

Console.WriteLine("Сумма={0},

Ваш текущий баланс={1}", sum,balance);

break;

case -2:

Console.WriteLine("Операция снятия денег не выполнена!");

Console.WriteLine("Сумма должна быть не больше баланса!");

Console.WriteLine("Сумма={0},

Ваш текущий баланс={1}", sum,balance);

break;

default:

Console.WriteLine("Неизвестная операция!");

break;

}

}

}//Account1

Сравнивая этот класс с классом Account, можно видеть, что число полей сократилось с пяти до двух, упростились основные методы getMoney и putMoney. Но, в качестве платы, у класса появился дополнительный метод balance , многократно вызываемый, и у метода Mes теперь появились два аргумента. Какой класс лучше? Однозначно сказать нельзя, все зависит от контекста, от приоритетов, заданных при создании конкретной системы.

Приведу процедуру класса Testing, тестирующую работу с классами Account и Account1;

public void TestAccounts

{

Account myAccount = new Account;

myAccount.putMoney(6000);

myAccount.getMoney(2500);

myAccount.putMoney(1000);

myAccount.getMoney(4000);

myAccount.getMoney(1000);

//Аналогичная работа с классом Account1

Console.WriteLine("Новый класс и новый счет!");

Accountl myAccount1 = new Account1;

myAccount1.putMoney(6000);

myAccount1.getMoney(2500);

myAccount1.putMoney(1000);

myAccount1.getMoney(4000);

myAccount1.getMoney(1000);

}

На рис. 9.1 показаны результаты работы этой процедуры.

Рис. 9.1. Тестирование классов Account и Account1

Функции с побочным эффектом

Функция называется функцией с побочным эффектом, если помимо результата, вычисляемого функцией и возвращаемого ей в операторе return, она имеет выходные аргументы с ключевыми словами ref и out. В языках C/C++ функции с побочным эффектом применяются сплошь и рядом. Хороший стиль ОО-программирования не рекомендует

использование таких функций. Выражения, использующие функции с побочным эффектом, могут потерять свои прекрасные свойства, присущие им в математике. Если f(а) — функция с побочным эффектом, то a+f(а) может быть не равно f(а)+а, так что теряется коммутативность операции сложения.

Примером такой функции является функция f, приведенная выше. Вот тест, демонстрирующий потерю коммутативности сложения при работе с этой функцией.

/// <summary>

/// тестирование побочного эффекта

/// </summary>

public void TestSideEffect

{

int a = 0, b=0, c=0;

a =1; b = a + f(ref a);

a =1; с = f(ref a)+ a;

Console.WriteLine("a={0}, b={1}, c={2}",a,b,c);

}

На рис. 9.2 показаны результаты работы этого метода.

Рис. 9.2. Демонстрация вызова функции с побочным эффектом

Обратите внимание на полезность указания ключевого слова ref в момент вызова. Его появление хоть как-то оправдывает не коммутативность сложения.

Методы. Перегрузка

Должно ли быть уникальным имя метода в классе? Нет, этого не требуется. Более того, проектирование методов с одним и тем же именем является частью стиля программирования на C++ и стиля С#.

Существование в классе методов с одним и тем же именем называется перегрузкой, а сами одноименные методы называются перегруженными.

Перегрузка методов полезна, когда требуется решать подобные задачи с разным набором аргументов. Типичный пример — это нахождение площади треугольника. Площадь можно вычислить потрем сторонам, по двум углам и стороне, по двум сторонам и углу между ними и при многих других наборах аргументов. Считается удобным во всех случаях иметь для метода одно имя, например Square, и всегда, когда нужно вычислить площадь, не задумываясь, вызывать метод Square, передавая ему известные в данный момент аргументы.

Перегрузка характерна и для знаков операций. В зависимости от типов аргументов, один и тот же знак может выполнять фактически разные операции. Классическим примером является знак операции сложения +, который играет роль операции сложения не только для арифметических данных разных типов, но и выполняет конкатенацию строк.

О перегрузке операций при определении класса будет подробно сказано в лекции, посвященной классам.

Перегрузка требует уточнения семантики вызова метода. Когда встречается вызов неперегруженного метода, то имя метода в вызове однозначно определяет, тело какого метода должно выполняться в точке вызова. Когда же метод перегружен, то знания имени недостаточно — оно не уникально. Уникальной характеристикой перегруженных методов является их сигнатура. Перегруженные методы, имея одинаковое имя, должны отличаться либо числом аргументов, либо их типами, либо ключевыми словами (заметьте: с точки зрения сигнатуры, ключевые слова ref и out не отличаются). Уникальность сигнатуры позволяет вызвать требуемый перегруженный метод.

Поделиться с друзьями: