- •Классы. Создание экземпляров класса. Особенности перегрузки конструкторов
- •Классы: особенности инициализации полей, поля const и readonly
- •Статические элементы класса. Статический конструктор.
- •Индексаторы
- •Механизмы наследования. Объявление наследования.
- •Конструкторы производных и базовых классов. Использование ключевого слова base.
- •Скрытие наследуемых элементов.
- •Переопределение наследуемых элементов.
- •Полиморфное поведение производных классов.
- •Абстрактные методы и классы.
- •Интерфейсы. Операции is и as.
- •Разработка и использование интерфейсов.
- •Делегаты.
- •События. Правила использования стандартных делегатов.
Конструкторы производных и базовых классов. Использование ключевого слова base.
Допустим, что у нас есть некоторый класс, который почти подходит для нашей конкретной задачи. Почти, но не совсем. Что-то (некоторые методы) в этом классе надо изменить, что-то - добавить. Наследование как раз и служит для этого. При наследовании мы объявляем наш класс потомком другого класса. И наш класс-потомок автоматически приобретает всё, что было в базовом классе. Причем вызов конструктора базового классов может быть осуществлен как явно, так и автоматически.
Доп-ые возможности предоставляет явный (непосредственный)
вызов конструкторов (если они перегружены) базового класса (если не перегружены - смысла вызывать нет – будет автовызов). В языке C# в производном может быть вызван конструктор только непосредственного базового класса.
В примере рассмотрим явный вызов базового класса:
namespace Class
{ class A
{ int B; protected double C;
protected int b { get { return B; } }
public A(int b, double c) { B = b; C = c; } }
class A1 : A
{ double D;
public A1(int a, double b) : base(a + 1, b + 2)
{ D = b + 3; }
public double sum
{ get { return b + C + D; } } }
class Program
{ static void Main()
{ A1 obj = new A1(1, 1);
Console.WriteLine(obj.sum); } } }
9 - на экране
ключевое слово base может быть использовано для вызова конструктора базового класса, для доступа к переопределённым элементам (методам,свойствам) базового класса.
Скрытие наследуемых элементов.
В некоторых ситуациях в производном классе необходимо заменить наследуемый элемент собственной реализацией. Сделать это можно и с полем и с методом.
namespace Class
{ class D
{ int A = 1;
protected int a { get { return A; } } }
class Dplus : D
{ int A = 2;
new public int a { get { return A + base.a; } } }
class Program
{ static void Main()
{ Dplus obj = new Dplus();
Console.WriteLine("{0}", obj.a); } } }
3 - на экране
Если бы не использовалось ключевое слово new в строчке new public int a { get { return A + base.a; } } трансляция проходила бы с предупреждением.
Доступ с помощью base к сокрытым элементам базового класса допустим только на одной цепи наследования, например, конструкция base.base.Имя уже недопустима.
new, здесь служит не операцией, а модификатором.
new public int a { get { return A + base.a; } } транслятору важно убедиться, что скрытие сделано осознано!
Переопределение наследуемых элементов.
Каждый производный класс может переопределить метод или свойство базового класса, если в базовом они были объявлены с модификатором virtual. В производном классе переопределение должно начинаться с модификатора override и абсолютно точно соответствовать типу, имени и сигнатуре заменяемого метода.
Виртуальным называется метод, объявляемый с помощью ключевого слова virtual в базовом классе и переопределяемый в одном или нескольких производ классах. Таким образом, каждый производ класс может иметь собственную версию виртуального метода.
Виртуальный метод нельзя определять как статический (с использованием слова s t a t i c ) или абстрактный (с использ. слова a b s t r a c t)
Перекрыть метод (или свойство) можно и в том случае, когда элемент объявлен без модификатора virtual. В этом случае вместо модификатора virtual необходимо использовать new(уже там где override). Разница лишь в том, что на переопределении метода с помощью new, в данной ветви наследования прерывается система виртуальных методов.
Если переопределить в производном классе (с помощью override) можно только методы, то перекрыть (с помощью new) можно и поля и вложенные классы.
namespace Class {
class D
{ public string GetName() { return "Класс D"; } }
class D1 : D
{ public new string GetName() { return "Класс D1"; }
public string GetName2()
{ return base.GetName() + "->" + GetName(); } }
class A
{ public virtual string а() {return "Класс А"; } }
class A1: A
{public override string а() { return "Класс А1"; } } class Program
{static void Main()
{ D obj = new D Console.WriteLine(obj.GetName());
D1 obj1 = new D1(); Console.WriteLine(obj1.GetName2());
A obj2 = new A(); Console.WriteLine(obj2.а());
A1 obj3 = new A1(); Console.WriteLine(obj3.а());}}}
class D class D->class D1 class A class A1