
Перегрузка операций
В класс Animals можно добавить новое свойство Weight. Перегрузка операций позволяет предоставить логику неявного использования свойства Weight, чтобы можно было упростить пример (1) и получить (2):
1)if (cowA.Weight>cowB.Weight)
{
}
2)if (cowA>cowB)
{
}
В примере операция «больше» перегружена. Перегруженной так же называется операция, для которой написан выполняющий её код. Этот код добавляется в определение одного из классов, для экземпляров которого должна выполняться перегрузка операции. Аналогично можно добавлять перегрузку операций для работы с разными классами. Перегрузка возможна только для операций, существующих в языке C#; новые операции создавать нельзя.
Наследование от общего предка:
Проблема коллизии возникает если два или более интерфейса имеют методы с одинаковыми именами или сигнатурами. Если имена совпадают, но сигнатуры различаются, то используется перегрузка.
Необязательные аргументы
В определении метода, конструктора, индексатора или делегата можно указать, что параметры являются обязательными или необязательными.При каждом вызове необходимо указывать аргументы для всех обязательных параметров, но можно опустить аргументы для необязательных параметров.
В рамках определения каждого необязательного параметра задается его значение по умолчанию.Если для параметра не передается аргумент, используется значение по умолчанию.Значения по умолчанию должны быть константами.
Необязательные параметры определяются в конце списка параметров после всех обязательных параметров.Если вызывающий объект задает аргумент для какого-либо из последующих необязательных параметров, он должен задать аргументы для всех предшествующих необязательных параметров.Разделенные запятыми пустые позиции в списке аргументов не поддерживаются.Например, в следующем коде метод экземпляра ExampleMethod определен одним или двумя необязательными параметра
C#
public void ExampleMethod(int required, string optionalstr = "default string",
int optionalint = 10)
Следующий вызов ExampleMethod вызывает ошибку компилятора, поскольку аргумент предоставлен для третьего параметра, а не для второго.
//anExample.ExampleMethod(3, ,4);
Но если имя третьего параметра известно, задачу можно выполнить с использованием именованного аргумента.
anExample.ExampleMethod(3, optionalint: 4);
IntelliSense использует квадратные скобки для указания необязательных параметров.
17
Виртуальным называется такой метод, который объявляется как virtual в базовом классе. Виртуальный метод отличается тем, что он может быть переопределен в одном или нескольких производных классах. Следовательно, у каждого производного класса может быть свой вариант виртуального метода. При их вызове по ссылке на базовый класс средствами языка С# определяется именно тот вариант виртуального метода, который следует вызывать, исходя из типа объекта, к которому происходит обращение по ссылке, причем это делается во время выполнения. Поэтому при ссылке на разные типы объектов выполняются разные варианты виртуального метода. Иными словами, вариант выполняемого виртуального метода выбирается по типу объекта, а не по типу ссылки на этот объект.
Метод объявляется как виртуальный в базовом классе с помощью ключевого слова virtual, указываемого перед его именем. Когда же виртуальный метод переопределяется в производном классе, то для этого используется модификатор override. А сам процесс повторного определения виртуального метода в производном классе называется переопределением метода. При переопределении имя, возвращаемый тип и сигнатура переопределяющего метода должны быть точно такими же, как и у того виртуального метода, который переопределяется. Кроме того, виртуальный метод не может быть объявлен как static или abstract.
Если при наличии многоуровневой иерархии виртуальный метод не переопределяется в производном классе, то выполняется ближайший его вариант, обнаруживаемый вверх по иерархии.
Пример:
// Создаем виртуальный метод
public virtual string FontInfo(Font obj)
{
string s = "Информация о шрифте: \n------------------\n\n" +
"Тип шрифта: " + typeFont +
"\nРазмер шрифта: " + fontSize + "\n";
return s;
}
}
// Производный класс 1 уровня
class ColorFont : Font
{
byte Color;
public ColorFont(byte Color, string TypeFont, short FontSize)
: base(TypeFont, FontSize)
{
this.Color = Color;
}
// Переопределение для виртуального метода
public override string FontInfo(Font obj)
{
// Используется ссылка на метод определенный в базовом классе Font
return base.FontInfo(obj) + "Цвет шрифта: " + Color + "\n";
}
// Создадим виртуальное свойство
public virtual byte color
{
set
{
Color = value;
}
get
{
return Color;
}
}
}
18
Интерфейс представляет собой полностью абстрактный класс, все методы которого абстрактны.
От абстрактного класса интерфейс отличается некоторыми деталями в синтаксисе и поведении:
● синтаксическое отличие состоит в том, что методы интерфейса объявляются без указания модификатора доступа
● отличие в поведении заключается в более жестких требованиях к потомкам.
Интерфейсы позволяют частично справиться с таким существенным недостатком языка C#, как отсутствие множественного наследования классов. Обеспечить возможность классу иметь несколько родителей - один полноценный класс, а остальные в виде интерфейсов, - основное назначение интерфейсов. Интерфейс позволяет описывать некоторые желательные свойства, которыми могут обладать объекты разных классов.
Опишем некоторый интерфейс, задающий дополнительные свойства объектов класса:
public interface IProps
{
void Prop1(string s);
void Prop2 (string name, int val);
}
У этого интерфейса два метода, которые и должны будут реализовать все классы -наследники интерфейса.
Заметим, что у методов нет модификаторов доступа. Класс, наследующий интерфейс и реализующий его методы, может реализовать их явно, объявляя соответствующие методы класса открытыми.
Вот пример:
public class Clain:IProps
{
public Clain() {}
public void Prop1(string s)
{
Console.WriteLine(s);
}
public void Prop2(string name, int val)
{
Console.WriteLine("name = {0}, val ={1}", name, val);
}
}//Clain - Класс реализует наследников.
19