Перегрузка методов и операций в классах

Автор работы: Пользователь скрыл имя, 30 Марта 2013 в 14:08, лекция

Краткое описание

При определении методов какого-нибудь класса в программах необходимо указать тип возвращаемого методом значения, а также количество параметров и тип каждого из них.
Например, программистом была разработана функция с именем sum(), которая суммировала два целых значения. Если требуется использовать подобную функцию для сложения трех целых значений, следует создать функцию с другим именем. Аналогично если требуется использовать подобную функцию для сложения значений типа float, то необходимо еще одна функция с еще одним именем.

Прикрепленные файлы: 1 файл

Лекция 18. Перегрузка операций.doc

— 114.00 Кб (Скачать документ)

Лекция 18. Перегрузка методов и операций в классах

 

Перегрузка методов

При определении методов какого-нибудь класса в программах необходимо указать тип возвращаемого методом значения, а также количество параметров и тип каждого из них.

Например, программистом была разработана функция с именем sum(), которая суммировала два целых значения. Если требуется использовать подобную функцию для сложения трех целых значений,  следует создать функцию с другим именем. Аналогично если требуется использовать подобную функцию для сложения значений типа float, то необходимо еще одна функция с еще одним именем.

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

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


Перегрузка методов – это один из способов, которым достигается полиморфизм в языке С#. Две и более функции могут иметь одно и то же имя, а отличаться набором аргументов в интерфейсе (описании).

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

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


Перегрузка операций

Как известно, в языке  С# тип переменной определяет набор значений, которые она может хранить, а также набор операций, которые можно выполнять над этой переменной. Например, над значением переменной типа int программа может выполнять сложение, вычитание, умножение и деление. С другой стороны, использование оператора “плюс” для сложения двух экземпляров реализованного программистом класса лишено смысла.

Когда в программе определяется класс, то по существу определяется новый  тип данных. Тогда язык C# позволяет определить операции, соответствующие этому новому типу данных.

Перегрузка  операций состоит в изменении смысла операции при использовании его с определенным классом.


Например, пусть имеется:

myclass a,bc;…//a,b,c-экземпляры класса myclass

c=a+b; //перегруженная операция сложения для класса myclass

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

Общий синтаксис объявления перегруженной операции:

[атрибуты] спецификаторы operator тело операции,

где:

Спецификаторы – public,static,extern

operator – ключевое слово, определяющее перегруженную операцию

тело операции-действия, которые выполняются при использовании операции в выражении

Перегружать можно только стандартные операции.


 

Алгоритм перегрузки операции:

  1. Определить класс, которому данная операция будет назначена.
  2. Для перегрузки операций используется ключевое слово operator.
  3. Переопределяя операцию, необходимо указать метод, который C# вызывает каждый раз, когда класс использует перегруженную операцию. Этот метод, в свою очередь, выполняет соответствующую операцию.

 

Правила перегрузки операции:

  1. Операция должна быть объявлена как public static
  2. Параметры в операцию должны передаваться по значению (не ref, не out)
  3. Двух одинаковых перегруженных операций в классе не должно быть

 

Если программа перегружает  операцию для определенного класса, то смысл этой операции изменяется только для указанного класса, оставшаяся часть программы будет продолжать использовать эту операцию для выполнения ее стандартных действий.

Перегрузка  унарных операций

К унарным операциям, которые можно перегружать в  языке С# относятся:

    • унарные  + и –
    • логическое !,
    • ++,--
    • true, false – обычно перегружаются для типов SQL

Синтаксис объявления перегруженной  унарной операции:

public static   тип_возвр_знач  operator   унарная_операция  (один параметр),

где параметр – это класс, для  которого перегружается данная операция

Например,

public static myclass operator ++(myclass x)

public static int operator +(myclass x)

public static bool operator  true(myclass x)

Перегруженная операция возвращает:

    • унарные  + и –, ! величину любого типа
    • ++,-- величину типа класса
    • true, false – величину типа bool

Префиксные и постфиксные ++ и – не различаются при перегрузке.


 

Пример перегрузки унарных  операций на примере класса

“Одномерный массив”

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.length:y.length;

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, которые программисты используют в своих классах:

 

  • public virtual bool Equals (object obj); - метод возвращает True или False в зависимости от того, ссылается ли параметр obj и вызывающий экземпляр класса на одну и ту же область памяти. Этот же метод можно использовать с двумя параметрами.
  • public virtual int GetHashCode (); - формирует хэш-код объекта и возвращает число, однозначно идентифицирующее объект. Это число может использоваться в различных структурах данных и алгоритмах библиотеки.

Обычно метод GetHashCode() перегружается, если используется перегрузка метода Equals().


  • public Type GetType(); -  возвращает текущий тип объекта, а не тип ссылки. Тип Type – это абстрактный базовый класс, который получает информацию (тип данных) об экземпляре класса не, как о ссылке, а как о простой переменной класса.

Для того, что бы в основной программе  перегрузить операции сравнения  с использованием методов класса object необходимо:

1. Перегрузить метод Equals()

2. В данном методе использовать метод GetType()

3. Перегрузить метод GetHashCode()

4. В основной программе использовать операции сравнения:  «==», «!=» и т.д.


 

Обычно операции сравнения перегружаются  только парами.

 

Чаще всего в классах  при перегрузке операции сравнения  обеспечивают сравнения значений экземпляров  класса, а не их ссылок.     


 

Пример перегрузки операций сравнения с использованием стандартных методов класса Object

namespace ConsoleApplication1

{

    class Monster

    {

        public Monster(int сила, int умение, string имя)

        {

            this.сила = сила;

            this.умение = умение;

            this.имя = имя;

        }

/* В  данном методе сначала сравнивается  экземпляр класса с "пустой" областью памяти и сравниваются  два экземпляра класса на соотвествие  типов и если одно из этих  условий не выполняется возврщается False. Если же два экземпляра одного и того же класса «равны», то возвращается значение True, только в том случае, если все поля обоих классов совпадают.*/

        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("Монстры не равны"); // использование перегруженной операции сравнения на равенство

Информация о работе Перегрузка методов и операций в классах