Автор работы: Пользователь скрыл имя, 30 Марта 2013 в 14:08, лекция
При определении методов какого-нибудь класса в программах необходимо указать тип возвращаемого методом значения, а также количество параметров и тип каждого из них.
Например, программистом была разработана функция с именем sum(), которая суммировала два целых значения. Если требуется использовать подобную функцию для сложения трех целых значений, следует создать функцию с другим именем. Аналогично если требуется использовать подобную функцию для сложения значений типа float, то необходимо еще одна функция с еще одним именем.
Лекция 18. Перегрузка методов и операций в классах
Перегрузка методов
При определении методов какого-нибудь класса в программах необходимо указать тип возвращаемого методом значения, а также количество параметров и тип каждого из них.
Например, программистом была разработана функция с именем sum(), которая суммировала два целых значения. Если требуется использовать подобную функцию для сложения трех целых значений, следует создать функцию с другим именем. Аналогично если требуется использовать подобную функцию для сложения значений типа float, то необходимо еще одна функция с еще одним именем.
Чтобы избежать дублирования функций, язык C# позволяет определять несколько функций с одним и тем же именем. В процессе компиляции C# принимает во внимание количество аргументов, используемых каждой функцией, и затем вызывает именно требуемую функцию. Предоставление компилятору выбора среди нескольких функций называется перегрузкой. Перегрузка является одним из способов реализации полиморфизма.
Перегрузка методов позволяет использовать одно и то же имя для нескольких функций с разным количеством или разным типом параметров.
Перегрузка методов – это один из способов, которым достигается полиморфизм в языке С#. Две и более функции могут иметь одно и то же имя, а отличаться набором аргументов в интерфейсе (описании).
Полиморфизм – позволяет использовать один и тот же интерфейс при реализации целого круга различных действий.
Наиболее распространенным видом перегрузки методов является перегрузка конструкторов в классе.
Как известно, в языке С# тип переменной определяет набор значений, которые она может хранить, а также набор операций, которые можно выполнять над этой переменной. Например, над значением переменной типа int программа может выполнять сложение, вычитание, умножение и деление. С другой стороны, использование оператора “плюс” для сложения двух экземпляров реализованного программистом класса лишено смысла.
Когда в программе определяется класс, то по существу определяется новый тип данных. Тогда язык C# позволяет определить операции, соответствующие этому новому типу данных.
Перегрузка операций состоит в изменении смысла операции при использовании его с определенным классом.
Например, пусть имеется:
myclass a,bc;…//a,b,c-экземпляры класса myclass
c=a+b; //перегруженная операция сложения для класса myclass
Перегрузка операций
обычно применяется для классов,
описывающих математические или
физические понятия, то есть таких классов,
для которых требуется
Общий синтаксис объявления перегруженной операции:
[атрибуты] спецификаторы operator тело операции,
где:
Спецификаторы – public,static,extern
operator – ключевое слово, определяющее перегруженную операцию
тело операции-действия, которые выполняются при использовании операции в выражении
Перегружать можно только стандартные операции.
Алгоритм перегрузки операции:
Правила перегрузки операции:
Если программа перегружает операцию для определенного класса, то смысл этой операции изменяется только для указанного класса, оставшаяся часть программы будет продолжать использовать эту операцию для выполнения ее стандартных действий.
Перегрузка унарных операций
К унарным операциям, которые можно перегружать в языке С# относятся:
Синтаксис объявления перегруженной унарной операции:
public static тип_возвр_знач operator унарная_операция (один параметр),
где параметр – это класс, для которого перегружается данная операция
Например,
public static myclass operator ++(myclass x)
public static int operator +(myclass x)
public static bool operator true(myclass x)
Перегруженная операция возвращает:
Префиксные и постфиксные ++ и – не различаются при перегрузке.
Пример перегрузки унарных операций на примере класса
“Одномерный массив”
class MyArray
{
public MyArray(int size)
{
length =size;
a=new int[length];
}
public MyArray(params int [] mas)
{
length =mas.length;
a=new int[length];
for (int i=0;i<length;i++)
a[i]=mas[i];
}
public static MyArray operator ++(MyArray x) //перегрузка унарного оператора ++
{
MyArray temp=new MyArray(x.length);
for (int i=0;i<length;i++)
temp[i]=++x.a[i]; //попробуйте temp.a[i]=++x.a[i]
return temp;
}
//индексатор, в случае выхода за рамки массива – генерируется исключение!
public int this [int i]
{
get {if (i>=0 && i<length) return a[i]; else throw new IndexOutOfRangeException();}
set { if (i>=0 && i<length) a[i]=value; else throw new IndexOutOfRangeException();}
}
public void Print(string name)
{
Console.WriteLine(name+”:”);
for (int i=0;i<length;i++)
Console.WriteLine(“\t”+a[i]);
Console.WriteLine();
}
public void Enter()
{
//в цикле - ввод элементов массива – реализуйте сами!
}
//данные класса – сам массив и его размерность
int [] a;
int length;
}
…Main()
{
try
{
MyArray a1=new MyArray(5,2,-1,1,-2);
a1.Print(“Первый массив ”);
a1++; //теперь к экземпляру класса можно применить операцию ++
a1.Print(“Использование операции ++ для всех элементов массива ”);
MyArray a2=new MyArray(5);
a2.Enter();
a2.Print(“Второй массив ”);
a2++;
a2.Print(“Использование операции ++ для всех элементов массива”);
}
catch (Exception e)
{Console.WriteLine(e.Message);
}…
Перегрузка бинарных операций
К бинарным операциям, которые можно перегружать в языке С# относятся:
Синтаксис объявления перегруженной бинарной операции:
public static тип_возвр_знач operator бинарная_операция (параметр1, параметр2),
где параметр – это класс, для которого перегружается данная операция, не обязательно 2 параметра будут экземплярами класса. Перегруженная бинарная операция может возвращать величину любого типа.
Например,
public static myclass operator +(myclass x, myclass y)
public static myclass operator +(myclass x,int y)
public static bool operator = =(myclass x,myclass y)
Операции сравнения (= =,!=,>,<,>=,<=) определяются только парами и обычно возвращают логическое значение. Перегрузка операций отношения будет иллюстрирована в следующей лекции с использованием интерфейсов.
Пример перегрузки бинарных операций на примере класса
“Одномерный массив”
//Перегружает операция сложения(+) либо двух массивов, либо массива и целого числа (то есть к //каждому элементу массива будет прибавлено это число)
class MyArray
{
public MyArray(int size)
{
length =size;
a=new int[length];
}
public MyArray(params int [] mas)
{
length =mas.length;
a=new int[length];
for (int i=0;i<length;i++)
a[i]=mas[i];
}
//перегрузка бинарного оператора + - сложение двух массивов (как экземпляров класса)
public static MyArray operator +(MyArray x, MyArray y)
{
int all_len=x.length<y.length?x.
MyArray temp=new MyArray(all_len);
for (int i=0;i<all_len;i++)
temp[i]=x[i]+y[i]; //попробуйте temp.a[i]=x.a[i]+y.a[i]!!!
return temp;
}
//перегрузка бинарного оператора + - сложение массива и целого числа
public static MyArray operator +(MyArray x, int y)
{
MyArray temp=new MyArray(x.length);
for (int i=0;i<x.length;i++)
temp[i]=x[i]+y; //попробуйте temp.a[i]=x.a[i]+y!!!
return temp;
}
public static MyArray operator ++(MyArray x) //перегрузка унарного оператора ++
{
MyArray temp=new MyArray(x.length);
for (int i=0;i<length;i++)
temp[i]=++x.a[i];
return temp;
}
//индексатор, в случае выхода за рамки массива – генерируется исключение!
public int this [int i]
{
get {if (i>=0 && i<length) return a[i]; else throw new IndexOutOfRangeException();}
set { if (i>=0 && i<length) a[i]=value; else throw new IndexOutOfRangeException();}
}
public void Print(string name)
{
Console.WriteLine(name+”:”);
for (int i=0;i<length;i++)
Console.WriteLine(“\t”+a[i]);
Console.WriteLine();
}
public void Enter()
{
//в цикле - ввод элементов массива – реализуйте сами!
}
//данные класса – сам массив и его размерность
int [] a;
int length;
}
…Main()
{
try
{
MyArray a1=new MyArray(5,2,-1,1,-2);
a1.Print(“Первый массив ”);
MyArray a2=new MyArray(5);
a2.Enter();
a2.Print(“Второй массив ”);
a2++;
a2.Print(“Использование операции ++ для всех элементов массива”);
MyArray a3=a1+a2;
а3.Print(“Сумма массивов первого и второго”);
a1=a1+100;
a1.Print(“Первый массив плюс 100 ”);
//ТАК делать не желательно, так как результат будет не всегда верен!!!
a2+=++a2+1; //!!!! Операция += не перегружена, вместо этого выполняется:
//a2=(++a2+1)+a2(уже измененное!!!)
a2.Print(“(++a2+1), +a2”);
}
catch (Exception e)
{Console.WriteLine(e.Message);
}…
Перегрузку операций можно осуществить с помощью открытых методов класса System.Object
Класс System.Object
Класс Object является корневым классом всей библиотеки объектов .NET и обеспечивает всех своих наследников всеми методами, которые они могут либо использовать без изменений, либо переопределять. Ниже перечислены открытые методы класса Object, которые программисты используют в своих классах:
Обычно метод GetHashCode() перегружается, если используется перегрузка метода Equals().
Для того, что бы в основной программе перегрузить операции сравнения с использованием методов класса object необходимо:
1. Перегрузить метод Equals()
2. В данном методе использовать метод GetType()
3. Перегрузить метод GetHashCode()
4. В основной программе использовать операции сравнения: «==», «!=» и т.д.
Обычно операции сравнения перегружаются только парами.
Чаще всего в классах при перегрузке операции сравнения обеспечивают сравнения значений экземпляров класса, а не их ссылок.
Пример перегрузки операций сравнения с использованием стандартных методов класса Object
namespace ConsoleApplication1
{
class Monster
{
public Monster(int сила, int умение, string имя)
{
this.сила = сила;
this.умение = умение;
this.имя = имя;
}
/* В
данном методе сначала
public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType()) return false;
Monster temp = (Monster)obj;
return (сила == temp.сила && умение == temp.умение && имя == temp.имя);
}
public override int GetHashCode()// Данный метод возвращает целое число, которое однозначно иденцифицирует экземпляр класса по имени.
{
return имя.GetHashCode();
}
public override string ToString()
{
return string.Format("Монстр {0} Сила {1} Умение {2}", имя, сила, умение);
}
string имя; //данные класса
int сила;
int умение;
} class Program
{
static void Main(string[] args)
{
Monster X = new Monster(100, 100, "Дима");
Monster Y = new Monster(100, 100, "Дима");
Monster Z = X; //Использование операции “присвоить”
if (X == Y) Console.WriteLine("Монстры равны!");
else Console.WriteLine("Монстры не равны"); // использование перегруженной операции сравнения на равенство