Перегрузка операторов x = a + b результат 1-й операнд2-й операнд оператор По количеству операндов операторы делятся на: унарные (один операнд) бинарные.

Презентация:



Advertisements
Похожие презентации
В С# предусмотрены средства для создания пользовательских классов-контейнеров, к внутренним элементам которых можно обращаться при помощи того же оператора.
Advertisements

Индексаторы и операции классов. Лекция 5. Индексаторы. Если в классе есть скрытое поле, представляющее собой набор элементов, например, массив, то в нем.
Наследование Наследование – это отношение является между классами. class Person { string first_name; int birth_year;... } class Student : Person { float.
Учебный курс Объектно-ориентированный анализ и программирование Лекция 7 Методы как средство реализации операций Лекции читает кандидат технических наук.
АССОЦИАТИВНЫЕ КОЛЛЕКЦИИ Лекция 6 1. Отличие от последовательных 2 В последовательной коллекции каждый элемент ассоциируется с номером, начиная с 0. В.
Высокоуровневые методы информатики и программирования Лекция 14 Интерфейсы.
Высокоуровневые методы информатики и программирования Лекция 8 Свойства и операции классов.
Прикладное программирование кафедра прикладной и компьютерной оптики Полиморфизм.
ДЕЛЕГАТЫ Лекция 7 1. Зачем нужны делегаты 2 И данные, и код располагаются в памяти компьютера по определенным адресам. Передача адресов данных в C# происходит.
1 Переопределение операций Макаревич Л. Г.. 2 Зачем нужна перегрузка операций? class Complex { double re; double im; public: Complex(double r=0, double.
Обобщения ( generics) Обобщения – это классы, структуры, интерфейсы и методы, в которых некоторые типы сами являются параметрами. Эти типы перечисляются.
Кафедра ОСУ, Java 2004 Слайд 1 Наследование Наследование позволяет использовать существующий класс для определения новых классов, т.е. способствует.
Гайдар Магдануров Microsoft.
Гайдар Магдануров Microsoft.
Лекция 13. Введение в ООП. Часть 4 Красс Александр СПбГУ ИТМО, 2008.
Классы в С#. Перечисления С# Перечисление задает конечное множество возможных значений, которые могут получать объекты класса перечисление. [атрибуты][модификаторы]
2. Классы.Полиморфизм.. Перегрузка функций void f(); void f(int value); void f(doublevalue); void f(int value, int nextValue); … f(); f(12); f(12.0);
Методы классов. Методы класса [атрибуты][модификаторы] {void|тип_результата_функции} имя_метода ([список_формальных_аргументов]) { тело метода} Список.
САОД кафедра ОСУ 1 Основные абстрактные типы данных Схема процесса создания программ для решения прикладных задач ВУ.
Java. Part 2. Спецификаторы доступа public private protected не указан – доступ в пределах пакета Могут использоваться перед классами, методами, полями.
Транксрипт:

Перегрузка операторов x = a + b результат 1-й операнд2-й операнд оператор По количеству операндов операторы делятся на: унарные (один операнд) бинарные (два операнда) Общее понятие оператора Виды операторов: 1. Логические (==, !=,, =) 2. Математические (+, -, *, /, ++, --, %,

Список операторов Унарные операторы: +, -, !, ~, ++, --, true, false Бинарные операторы: +, -, *, /, %, &, |, ^, >, ==, !=, >, =, , new, is, sizeof, typeof 2

3 Оператор сравнения class Fraction { public int A { get; set; } public int B { get; set; } public static bool operator < (Fraction left, Fraction right) { return (left.A / left.B < right.A / right.B); } Fraction f1 = new Fraction { A = 2, B = 3 }; Fraction f2 = new Fraction { A = 3, B = 4 }; if (f1 < f2) { }

Перегрузка оператора – реализация статического операторного метода, определяющего результат применения данной операции к объекту(ам) класса. Цель перегрузки: обеспечить краткую и удобную форму записи операций над объектами, аналогично операциям над встроенными типами данных. Рекомендации: 1. Перегрузка как правило имеет смысл в случае тех типов, поведение которых подобно примитивным (например, классы, представляющие числа, математические объекты и т.п.). 2. Смысл перегружаемой операции для данного типа должен быть прозрачен.

Правила перегрузки 1. Перегрузка применима только к пользовательским типам, или их смеси со встроенными (т.е. как минимум один из операндов – объект вашего класса). 2. Перегружать можно только существующие операции. 3. При перегрузке нельзя изменить приоритет операций. 4. Параметры операторного метода передаются без ref, out, params. 5. При перегрузке симметричных операций необходимо реализовать оба варианта: != и ==,, …

Унарный минус class Vector2D { private double x; private double y; public Vector2D(double x, double y) { this.x = x; this.y = y; } public static Vector2D operator - (Vector2D v) { return new Vector2D(-v.x, -v.y); } Vector2D v1 = new Vector2D(15.5, 23.0); Vector2D v2 = -v1; 6

Префиксный инкремент class Vector2D { private double x; private double y; public Vector2D(double x, double y) { this.x = x; this.y = y; } public static Vector2D operator ++ (Vector2D v) { v.x++; v.y++; return v; } Vector2D v1 = new Vector2D(1, 1); Vector2D v2 = v1++; 7

Оператор явного преобразования class Fraction { private int a = 0; private int b = 0; public static explicit operator double (Fraction frac) { return (frac.a / frac.b); } Fraction f = new Fraction(); double fd = (double)f; double fd2 = f; //error Оператор явного не вызывается автоматически (неявно) 8

Оператор неявного преобразования - Оператор неявного может быть вызван явно; - Нельзя перегрузить обе формы; - Нельзя определять преобразования: в тип object, в производный тип, из одного интерфейса в другой. 9 class Fraction { private int a = 0; private int b = 0; public static implicit operator double (Fraction frac) { return (frac.a / frac.b); } Fraction f = new Fraction(); double fd2 = f; double fd = (double)f;

class Vector2D { private double x; private double y; public Vector2D() : this(0.0, 0.0) { } public Vector2D(double x, double y) { this.x = x; this.y = y; } public static Vector2D operator + (Vector2D a, Vector2D b) { Vector2D c = new Vector2D(); c.x = a.x + b.x; c.y = a.y + b.y; return c; //return new Vector2D(a.x + b.x, a.y + b.y); } Vector2D v1 = new Vector2D(15.5, 23.0); Vector2D v2 = new Vector2D(21.5, 40.5); Vector2D v3 = v1 + v2; Бинарный плюс 10

Индексаторы тип_элемента this [тип_индекса значение_индекса] { // Аксессор чтения get { } // Аксессор записи set { } 11

class Array { private float [] array; public Array(int size) { array = new float[size]; } public float this[int index] { get { if (index = this.array.Length) throw new IndexOutOfRangeException("Индекс за пределами!"); return this.array[index]; } set { if (index = this.array.Length) throw new IndexOutOfRangeException("Индекс за пределами!"); this.array[index] = value; } 12

class Program { static void Main() { try { Array someArray = new Array(10); someArray[5] = 1; float f = someArray[50]; } catch (Exception e) { Console.WriteLine(e.Message); } 1. Допустимо использовать только 1 аксессор. 2. В set-аксессор внешнее значение передается через value. 3. Индексатор можно перегружать. 4. Тип индекса и их количество – любое. 5. Индексатор нельзя объявлять как static 6. Тип индекса не может дополняться модификатором ref или out 13

class Time { private int hour = 0; private int min = 0; private int sec = 0; …. } class Program { static void Main() { Time t = new Time(); Console.WriteLine(t); // ??? } 14 Перегрузка ToString

class Time { private int hour = 0; private int min = 0; private int sec = 0; public override string ToString() { return string.Format("{0:00}:{1:00}:{2:00}", this.hour, this.min, this.sec); } … Time t = new Time(); Console.WriteLine(t); 15

Операторы сравнения В C# существует понятие 2-х видов сравнения: 1.Равенство ссылок. 2.Равенство значений. Time t1 = new Time(); // class Time Time t2 = t1; bool isSameObject1 = ( t1 == t2 ); bool isSameObject2 = System.Object.ReferenceEquals(t1, t2); 16 Для ссылочных типов (кроме string) оператор == по умолчанию сравнивает ссылки (также, как и ReferenceEquals).ReferenceEquals

17 Для типов по значению (кроме struct) оператор == сравнивает значения. int x = 0, y = 1; if (x == y) { } Point p1, p2; // struct Point bool isSameObject = ( p1 == p2 ); // Не определен!

{ … public override bool Equals(System.Object obj) { if (obj == null) return false; Time t = obj as Time; if ((System.Object)t == null) return false; return (hour == t.hour) && (min == t.min) && (sec == t.sec); } … } 18 Для сравнения ссылочных типов по значению перегружается метод Equals.

public bool Equals(Time t) { if ((object)t == null) { return false; } return (hour == t.hour) && (min == t.min) && (sec == t.sec); } public override int GetHashCode() { return hour ^ min ^ sec; } 19

Новая реализация Equals должна соответствовать гарантиям: 1.x.Equals(x) возвращает true. 2. x. Equals (y) возвращает то же значение, что и y. Equals (x). 3. если (x. Equals (y) && y. Equals (z)) возвращает true, то x. Equals (z) возвращает true. 4. Последовательные вызовы x. Equals (y) возвращают то же значение до тех пор, пока объекты, на которые ссылается x и y, не будут изменены. 5. x. Equals (null) возвращает false. 20 В Equals не следует выбрасывать исключения.

21 public static bool operator ==(ThreeDPoint a, ThreeDPoint b) { // If both are null, or both are same instance, return true. if (System.Object.ReferenceEquals(a, b)) { return true; } // If one is null, but not both, return false. if (((object)a == null) || ((object)b == null)) { return false; } // Return true if the fields match: return a.x == b.x && a.y == b.y && a.z == b.z; } public static bool operator !=(ThreeDPoint a, ThreeDPoint b) { return !(a == b); }

22 Для структур (которым по смыслу нужна операция сравнения): 1. Перегружаем ==. 3. Перегружаем Equals, для чего наследуем IEquatable. Для классов (чаще из области математики, кому реально нужны сравнения): 1. Перегружаем Equals (помня о 5 гарантиях). 2. Не перегружаем ==, он будет работать эквивалентно object.ReferenceEquals.