Скачать презентацию Наследование ü Наследование это отношение является между Скачать презентацию Наследование ü Наследование это отношение является между

5_C#_наследование.pptx

  • Количество слайдов: 19

Наследование ü Наследование – это отношение “является” между классами. Обобщение Конкретизация class Person { Наследование ü Наследование – это отношение “является” между классами. Обобщение Конкретизация class Person { string first_name; int birth_year; . . . } class Student : Person { float average_ball; . . . } Базовый класс Производный класс ü Производный класс наследует все поля и методы базового класса. ü C# не поддерживает множественное наследование. Класс может иметь только один непосредственный базовый класс. ü Наследование применимо только к классам. Структура не может быть ни базовым классом, ни производным.

Отношение агрегации и отношение наследования ü Наследование • отношение между классами; • сильная зависимость Отношение агрегации и отношение наследования ü Наследование • отношение между классами; • сильная зависимость между производным и базовым классом; • отношение задается на этапе компиляции и не может быть изменено в процессе выполнения программы. ü Агрегация (класс содержит ссылки на объекты других классов) • отношение между объектами; • слабая зависимость между агрегирующим и агрегируемым классами; • отношение может изменяться в процессе выполнения программы.

Наследование и конструкторы ü Конструктор базового класса вызывается при помощи ключевого слова base. class Наследование и конструкторы ü Конструктор базового класса вызывается при помощи ключевого слова base. class Person { public Person(string[] name) {. . . } } Вызов конструктора базового класса class Student : Person { public Student(string[] name, int course) : base(name) {. . . } } ü Если в базовом классе нет конструктора по умолчанию, то конструктор производного класса должен содержать явный вызов конструктора базового класса. ü Если в базовом классе есть конструктор по умолчанию, то его явный вызов в производном классе не обязателен.

Полиморфизм ü Полиморфизм дословно означает множественность форм или видов. ü Метод, определенный в базовом Полиморфизм ü Полиморфизм дословно означает множественность форм или видов. ü Метод, определенный в базовом классе, может быть реализован в любом из производных классов. Class Person { public virtual void Print. Data() {. . . } обозначение } полиморфного метода class Student : Person { public override void Print. Data() {. . . } class Teacher : Person { public override void Print. Data() {. . . } ü За одним именем могут скрываться разные реализации. void Some. Method(Person s) { s. Print. Data(); . . . } Student std = new Student(); Some. Method(std); Teacher tch = new Teacher(); Some. Method(tch);

Ранее и позднее связывание class Person { public virtual void Print. Data() {. . Ранее и позднее связывание class Person { public virtual void Print. Data() {. . . } } class Student : Person { public override Print. Data() {. . . } class Teacher : Person { public override void Print. Data() {. . . }. . . void Some. Method(Person ps) { ps. Print. Data(); . . . динамический тип ps не } известен в момент. . . компиляции Student std = new Student(); Some. Method(std); Teacher tch = new Teacher(); Some. Method(tch) ü Статический тип – тип переменной (выражения), которая используется для доступа к объекту. Всегда известен во время компиляции. ü Раннее связывание – вызов метода на основе статического типа. ü Объект производного класса всегда может быть неявно преобразован к базовому классу. ü Динамический тип – тип объекта, на который ссылается переменная или выражение. Может быть не известен на этапе компиляции. ü Позднее связывание – вызов метода на основе динамического типа.

Виртуальные методы ü Для определения полиморфного (виртуального) метода применяется ключевое слово virtual. Для переопределения Виртуальные методы ü Для определения полиморфного (виртуального) метода применяется ключевое слово virtual. Для переопределения виртуального метода используется ключевое слово override. ü Виртуальный метод не может быть статическим. class Person { public virtual void Print. Data() {. . . } Определение виртуального метода } class Student : Person { public override void Print. Data() {. . . } Переопределение виртуального метода. . Переопределенный метод также является } виртуальным и может быть class Teacher : Person { переопределен. public override void Print. Data() {. . . } void Some. Method(Person ps) { ps. Print. Data(); . . . Метод Print. Data будет вызван в } соответствии с динамическим типом ps

Виртуальный метод To. String() ü Метод To. String() определен в классе System. Object как Виртуальный метод To. String() ü Метод To. String() определен в классе System. Object как виртуальный: public class Object { public virtual string To. String(); … } ü В классе System. Console один из перегруженных методов Write. Line принимает параметр типа object: public class Console { public static void Write. Line( object value ); … } ü Метод Console. Write. Line ( object value ); • выводит пустую строку, если value == null; • выводит строку value. To. String() , если value != null.

Виртуальный метод To. String() -2 class Bs { protected string bs_name; public Bs (string Виртуальный метод To. String() -2 class Bs { protected string bs_name; public Bs (string bs_name) { this. bs_name = bs_name; } public override string To. String() { return "Bs: " + bs_name; } } class Dr : Bs { protected int dr_value; public Dr (int dr_value, string bs) : base (bs) { this. dr_value = dr_value; } public override string To. String() { return "Dr: " + bs_name + "t" + dr_value; } } static void Main(string[] args) { Bs[] list = new Bs[4]; list[0] = new Bs ("white"); list[2] = new Dr ( 123, "green"); list[3] = new Bs ("red"); for (int j=0; j

Переопределение невиртуальных методов ü Для переопределения невиртуального метода в производном классе используется ключевое слово Переопределение невиртуальных методов ü Для переопределения невиртуального метода в производном классе используется ключевое слово new. class Person { public void Output() {. . . } Определение невиртуального метода } class Student : Person { public new void Output() {. . . }. . . Переопределение (сокрытие) } невиртуального метода ü При вызове неполиморфного метода используется статический тип. Person ps = new Person(); ps. Output(); Student st = new Student(); st. Output(); // Будет вызван метод Output из класса Student Person ps 1 = new Student(); ps 1. Output(); // Будет вызван метод Output из класса Person

Виртуальные методы и new class A { public virtual void f() { Console. Write. Виртуальные методы и new class A { public virtual void f() { Console. Write. Line(“A. f”); } } class B : A { public override void f() { Console. Write. Line(“B. f”); } } class C : B { public new virtual void f() { Console. Write. Line(“C. f”); } } public static void Main (string[] args) { D d = new D(); A a = d; B b = d; C c = d; a. f(); // B b. f(); // B c. f(); // D d. f(); // D } class D : C { public override void f() { Console. Write. Line(“D. f”); } } ü Метод C. f не переопределяет, а скрывает B. f

Виртуальные методы и переопределение class B : A {…} class D : B {…} Виртуальные методы и переопределение class B : A {…} class D : B {…} A D d = new D(); A a = d; B b = d; B D a. fxx() b. fxx() f 0() из A из B virtual f 1() из A из B virtual f 2() override f 2() из D virtual f 3() override f 3() из B virtual f 4() override f 4() virtual f 4() из B virtual f 5() override f 5() из A из D f 6() virtual f 6() override f 6() из A из D

Виртуальные свойства ü Свойство определяется парой методов. Поэтому свойства могут быть виртуальными, абстрактными или Виртуальные свойства ü Свойство определяется парой методов. Поэтому свойства могут быть виртуальными, абстрактными или статическими. Свойства могут быть переопределены или скрыты. ü Тип виртуального свойства (только для чтения, только для записи, для чтения и для записи) переопределить нельзя. ü Индексатор может быть виртуальным.

Сокрытие полей данных ü В производном классе можно определить поле данных с тем же Сокрытие полей данных ü В производном классе можно определить поле данных с тем же именем, что и в базовом классе. class A { protected int a; public void f() { a = 10; // Присваивание полю данных класса A } } class B : A { public new int a; // Поле a класса B скрывает поле a класса A public void g() { a = 20; // Присваивание полю данных класса B } }

Явное обращение к полям и методам базового класса ü Для явного доступа к полям Явное обращение к полям и методам базового класса ü Для явного доступа к полям и методам базового класса в методах производного класса применяется ключевое слово base. public class A { public string str; public void f() {. . . } public virtual void g() {. . . } } public class B : A { public new string str; public new void f() {. . . } public override void g() {. . . } public void h() { base. str = “abc”; // Присваивание полю данных класса A base. f(); // Вызов метода класса А base. g(); // Вызов метода класса A } } ü Во внешнем методе : public static void Main (string[] args) { B b = new B(); ((A) b). f(); // Вызов метода класса А ((A) b). g(); // Вызов метода класса B }

Запечатанные (sealed) классы ü При помощи ключевого слова sealed можно обозначить класс как не Запечатанные (sealed) классы ü При помощи ключевого слова sealed можно обозначить класс как не предназначенный для наследования: namespace System { public sealed class String {. . . } } ü Применение ключевого слова sealed позволяет компилятору оптимизировать код. void f(String s) { String s 2 = s. Substring(1, 10); // Динамический тип } // известен и равен String

Абстрактные классы ü Во многих случаях виртуальный метод базового класса не выполняет никаких действий. Абстрактные классы ü Во многих случаях виртуальный метод базового класса не выполняет никаких действий. Методы, не имеющие реализации, называют абстрактными. Классы, содержащие абстрактные методы, также называют абстрактными. ü Абстрактные классы и методы объявляются при помощи ключевого слова abstract. ü Нельзя создать экземпляр абстрактного класса. Абстрактный класс используется только для создания производных классов. ü Абстрактные методы задают сигнатуры для определения в производных классах. abstract class Shape { public abstract void Draw(); . . . } class Rectangle : Shape { public override void Draw() {. . . } class Polygon : Shape { public override void Draw() {. . . }

Особенности работы с абстрактными классами abstract class Shape { public abstract void Draw(); . Особенности работы с абстрактными классами abstract class Shape { public abstract void Draw(); . . . } class Rectangle : Shape { public override void Draw() {. . . } ü Абстрактный метод всегда является виртуальным. ü Абстрактный класс может не содержать абстрактных методов. ü Абстрактный класс может иметь конструкторы. ü Абстрактный метод должен обязательно содержаться в абстрактном классе.

Преобразование типов ü Объект производного класса всегда может быть неявно преобразован к базовому классу. Преобразование типов ü Объект производного класса всегда может быть неявно преобразован к базовому классу. ü Для преобразования базового класса к производному требуется явное приведение типов. struct S { … } class C { …} … S s = new S(); C c = new C(); object o = s; C c 2 = (S)c; o = c; c 2 = (C)o; o = 5; s = (S)o; // // // Неявное преобразование Ошибка на этапе компиляции Неявное преобразование Правильное явное преобразование Неявное преобразование Исключение Invalid. Cast. Exception ü Неверное приведение типа может быть определено на этапе компиляции или на этапе выполнения программы. В последнем случае возникает исключение Invalid. Cast. Exception.

Операторы as и is ü Оператор is позволяет проверить, является ли динамический тип первого Операторы as и is ü Оператор is позволяет проверить, является ли динамический тип первого операнда совместимым с типом - вторым операндом. class Bs { … } class Dr : Bs { … } … object obj = 5; bool res 1 = obj is int; // true res 1 = obj is string; // false obj = new Dr(); res 1 = obj is Bs; // res 1 = obj is Dr; // true class Bs { class Dr : … object obj Bs b = obj Dr d = obj … } Bs { … } = new Dr(); as Bs; // b != null as Dr; // d != null string s = obj as string; // s == null ü Оператор as позволяет выполнять преобразование типов без возникновения исключения. ü Если преобразование не может быть выполнено, то результат оператора as равен null.