
- •Программирование и алгоритмические языки. Курс за третий семестр.
- •Введение в объектно-ориентированное программирование (ооп)
- •Идеологический обзор
- •Базовые принципы ооп
- •Наследование имён. Наследование значений.
- •Коллизия
- •Что такое имя процедуры?
- •Ооп как оперирование типами
- •Именование типов в c# Тип данных «класс»
- •Конструкторы и деструкторы
- •И нкапсуляция данных
- •Наследование (краткое введение)
- •Наследование реализации как уточнение семантики типа
- •Пополнение и переопределение методов Отношение пополнения интерфейса
- •Открытие реализации для проектирования классов - опция protected
- •Полиморфизм Полиморфизм как уточнение семантики типа переменной
- •Динамические методы как поддержка полиморфизма- опции static, virtual, override
- •Событийное программирование Обработка событий
- •Идея: Когда что-то вставляется, срабатывает некоторый предикат. Например, после вызывается команда проверки, каскадного удаления или какая-нибудь другая команда. Генераторы и приёмники сообщений
- •Событийное программирование нужно:
- •Событийный стиль в процедурном программировании - управление данными (на примере)
- •Событийное программирование в c# (delegate, event)
- •Введение в компонентное программирование
- •Объекты, реализующие интерфейсы
- •Частный случай общей проблемы взаимодействия программного обеспечения разных производителей на уровне исполняемого кода
- •Базовый интерфейс компонент
- •Проблема множественности иерархий
- •Коллизия имён
- •Коллизия реализации
- •«Симметричное» решение – агрегаты (декартовы произведения классов)
- •Множественное наследование
- •«Асимметричное» решение - именованные интерфейсы
- •Основные отличия интерфейса и абстрактного класса
- •Наследование интерфейса (компонентный подход)
- •Обработка исключений в ооп
- •Определение и генерация исключений в c#
- •Выбрасывание исключений
- •Захват исключения
- •Блок finally
- •Коды программ
Основные отличия интерфейса и абстрактного класса
1) -абстрактный класс может содержать свойства
-интерфейс не содержит свойств
2) -абстрактный класс может содержать тела методов
-интерфейс не содержит тел методов, только их объявление
3) -абстрактный класс наследуется (etxends)
-интерфейс реализуется (implements)
4) -наследник в абстрактном классе имеет только одного родителя
-наследник может реализовывать методы нескольких интерфейсов
5) -наследник не обязан содержать реализацию методов абстрактного класса-родителя
-наследник обязан содержать реализацию всех методов реализуемого интерфейса
Следовательно, интерфейс не часть класса, а частный случай - абстрактный класс, наследование которого обязывает к реализации.
Пример: иерархия животных (основная - по строению, вторичная - по передвижению):
// Компонентно-ориентированное программирование
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; // предоставляет типы, которые упрощают работу по написанию параллельного и асинхронного кода
namespace Hierarchy
{
class cAnimals
{
protected string Name;
public void SetName(string x)
{
this.Name = x;
}
public string GetName()
{
return Name;
}
public cAnimals() // конструктор по умолчанию
{
}
public cAnimals(string x) // конструктор
{
this.Name = x;
}
}
class cMammals : cAnimals // класс «Млекопитающие», который наследуется от класса «Животные»
{
}
class cFishes : cAnimals // класс «Рыбы»
{
}
class cBirds : cAnimals // класс «Птицы»
{
}
//Разница между интерфейсами и абстрактными классами
//предок обязан / может дать реализацию
//иными словами, здесь интерфейс не часть класса, но частный случай- абстрактный класс, наследование которого обязывает к реализации
abstract class FlyAble
{
public abstract void Fly();
}
//интерфейсы: только заголовки методов без модификаторов (public по умолчанию)
//в частности, нет полей (но может быть set-get) и невозможна инициализация
//движение с переменной скоростью
interface IMoveAble
{
void SetSpeed(int x); // фиксируем скорость
int GetSpeed(); //получаем скорость, с которой двигается животное
}
//вносится коллизия имён для демонстрации проблем множественного наследования
//ошибка проектирования?
//см. далее также обсуждение конфликта реализации и способы разрешения (склеивание, переименование)
interface IFlyAble : IMoveAble
{
void Fly();
}
interface IRunAble : IMoveAble
{
void Run();
}
interface ISwimAble : IMoveAble
{
void Swim();
}
class Elephant : cMammals, IRunAble, ISwimAble
{
//явное описание интерфейса - реализация:
void IRunAble.Run()
{
//выполнение метода:
Console.WriteLine("Elephant" + GetName() + "runs");
}
void ISwimAble.Swim()
{
//выполнение метода
Console.WriteLine("Elephant" + GetName() + "swims");
}
public Elephant()
{
}
public Elephant(string x)
{
this.Name= x;
}
//разрешение коллизии - "склеивание"
void IMoveAble.SetSpeed(int x) // сомнительно с точки зрения предметной области
{
}
int IMoveAble.GetSpeed()
{
return 0;
}
//иной вариант- переименование
//реализуем как закрытие, открываем под другими именами
// см. Duck
} //class Elephant
class Dolphin : cMammals, ISwimAble
{
//Явное описание интерфейса (реализация)
void ISwimAble.Swim()
{
//выполнение метода
}
void IMoveAble.SetSpeed(int x)// устанавливается скорость движениия
{
}
int IMoveAble.GetSpeed()
{
return 0;
}
} //class Dolphin
class Duck : cBirds, ISwimAble, IRunAble, IFlyAble
{
//Явное описание интерфейса-реализация:
void ISwimAble.Swim()
{
//Выполнение метода
}
void IRunAble.Run()
{
//выполнение метода
}
void IFlyAble.Fly()
{
//выполнение метода
}
void IMoveAble.SetSpeed(int x)
{
}
int IMoveAble.GetSpeed()
{
return 0;
}
}//class Duck
class Program
{
// запускалка
static void Main()
{
Elephant E1 = new Elephant();
E1.SetName("John");
//E1.Run_Method(); //ошибка - нужно явно выбирать интерфейс
((IRunAble)E1).Run(); //ok
IRunAble E2 = E1;
E2.Run(); // ok
//E2.SetName("???"); //ошибка
// объявление объекта интерфейсного класса
IRunAble E = new Elephant("Pete");
//E.SetName("???"); //ошибка
// объект, функционирующий по правилам метода
E.Run();
ISwimAble obj_Dolphin = new Dolphin();
obj_Dolphin.Swim;
ISwimAble obj_Duck_1= new Duck();
obj_Duck_1.Swim;
IRunAble obj_Duck_2= new Duck();
obj_Duck_2.Run();
IFlyAble obj_Duck_3= new Duck();
obj_Duck_3.Fly();
Console.ReadKey();
}
}// class Program
} //namespace Hierarchy