2013
Курс по програмиране на C#
Занятие №12
Полиморфизъм (част 2): Абстракция. Интерфейси.
Шаблонни типове и методи
Съдържание
• Абстрактни класове и членове
• Интерфейси
• Интерфейсите IEnumerable и IEnumerator
• Интерфейсът IDisposable
• Шаблонни типове
• Шаблонни методи
• Вградени шаблонни колекции
Полиморфизъм
• Полиморфизъм - преговор
– Основен принцип на ООП
– Еднотипна работа с разнотипни данни
– Обобщаване на възможности, но с различна реализация
– Обединяване на сходни функционалности в нещо общо
– Гъвкав и лесен начин за поддръжка на кода
– Статичен (compile-time) и динамичен (run-time)
– Презаписване на членове и оператори
– Виртуални членове и предефиниране
Абстракция
• Какво е „абстрактен клас “?
– Не може да бъде инстанциран директно
– Описва поведение, общо за йерархията от наследени класове
– Не се ангажира с пълната реализация на поведението
– Използва се като събирателен тип данни за променливи,
параметри и изрази
Абстракция
abstract class Shape2D
{
// Декларации на членове
}
abstract class Animal
{
// Декларации на членове
}
• Деклариране на абстрактни
класове
– Модификатор за достъп
(незадължителен)
– Ключова дума abstract
– Наименование на класа
– Родителски клас (незадължителен)
– Блок с декларации на членове
Деклариране на абстрактни класове - демо
// Демонстрация
Абстракция
• Какво е „абстрактен член“?
– Виртуален член на клас
– При декларирането му не е описано тяло (блок от операции)
– Описва сигнатурата на члена, но не и неговата реализация
– Представлява поведение, което от формална гледна точка е
сходно между различните подкласове, но няма обща реализация в
общия родителски клас
– Класът, в който е деклариран, задължително трябва да бъде
маркиран като абстрактен
– По време на изпълнение на програмата винаги се изпълнява
реализацията в някой от наследените класове
Абстракция
abstract class Shape2D
{
// Абстрактен метод
public abstract void InputFromConsole();
// Абстрактно свойство
// (само за четене)
public abstract double Area { get; }
public virtual void PrintToConsole()
{
// Използване на абстрактното
// свойство Area
Console.WriteLine(
"Area: {0}", Area);
}
}
• Деклариране и употреба на
абстрактни членове
– Ключовата дума virtual след
модификатора за достъп се заменя с
ключовата дума abstract
– Блокът/блоковете с операции на члена
се заменят с „;“
– Употребяват се идентично на
обикновени членове
Деклариране и употреба на абстрактни членове -
демо
// Демонстрация
Абстракция
• Наследяване на абстрактни класове
– Наследеният клас трябва да предефинира всички абстрактни
членове на абстрактния родителски клас
– В противен случай, самият той трябва да бъде маркиран като
абстрактен
– При предефиниране на абстрактен член не може да бъде
преизползвана реализацията в родителския клас (тъй като няма
такава)
– Веднъж предефиниран, съответният член е възможно, но не е
задължително да бъде предефиниран в наследените класове
надолу в йерархията
Наследяване на абстрактни класове - демо
// Демонстрация
Абстракция
• Приложения на абстракцията
– Предотвратяване на създаването на екземпляри от родителски (не
достатъчно конкретен) клас, който не е предназначен за
самостоятелна употреба
– Обединяване на сходното формално поведение, когато няма
нищо общо във вътрешната реализация
– Възможност за комбиниране на общи членове с реализация с
такива без
– Недостатък: не позволява комбиниране на отделни групи от
функционалности на произволен принцип, поради липсата на
множествено наследяване
Интерфейси
• Какво е „интерфейс“?
– Тип данни
– Декларира единствено поведение
– Не описва реализация на поведението
– Сходен с напълно абстрактен клас (клас без полета, всички
членове на който са абстрактни)
– Може да се разглежда като „договор“ между тип данни, който
реализира декларираното поведение, и код, който го използва
– Интерфейсите се имплементират от класове/структури –
имплементиращият тип е длъжен да предостави имплементация на
съответните членове (може и абстрактна)
– Един клас/структура може да имплементира няколко интерфейса
(множествено наследяване?)
Интерфейси
• Интерфейси в C#
– Референтни типове данни
– Не може да бъде създаден екземпляр на интерфейс
– Могат да декларират единствено методи, свойства и индексатори
– Всички членове са с публична видимост
– Всеки интерфейс може да наследява един или няколко други
интерфейса; при това той автоматично получава членовете,
декларирани в родителските интерфейси
– Интерфейс може да наследява единствено интерфейси
– Прието е да се именуват с представка I (от interface)
Интерфейси
// Интерфейс за обекти, които издават звуци
public interface ISoundMaker
{
void MakeSound();
}
// Интерфейс за обекти, които могат да се придвижват
public interface IMobileObject
{
void MoveТо(Point location);
}
// Интерфейс за обекти, които могат да се печатат
// на конзолата
interface IPrintableObject
{
void PrintToConsole();
}
// Интерфейс за равнинни фигури
interface IPlanarShape : IPrintableObject
{
double Perimeter { get; }
double Area { get; }
}
• Деклариране на интерфейси
– Модификатор за достъп
(незадължителен)
– Ключова дума interface
– Наименование на интерфейса
– Двоеточие
– Списък от родителски интерфейси
(незадължителен)
– Блок с декларации на членове
• Методи, свойства и индексатори
• Без модификатори за достъп
• Блоковете с операции се заменят с „;“
• Без ключови думи virtual и abstract
Деклариране на интерфейси - демо
// Демонстрация
Интерфейси
• Имплементиране на интерфейси в C#
– При деклариране на клас или структура може да бъдат указани
един или повече интерфейси, които типът данни имплементира
– В декларацията на типа данни трябва да бъдат имплементирани
всички членове, декларирани от съответните интерфейси
– Неявно имплементиране на член – деклариране на член с публична
видимост и със същата сигнатура по стандартния начин
– Явно имплементиране на член – деклариране на член със същата
сигнатура, като наименованието му се префиксира с
наименованието на съответния интерфейс и „.“
Интерфейси
• Имплементиране на интерфейси в C#
– Възможно е членовете да са абстрактни, така че да бъдат
предефинирани в наследен клас
– Възможно е член на интерфейса да бъде неявно имплементиран
от публичен член със същата сигнатура, който е бил деклариран в
родителски клас
– Всички наследени от текущият типове автоматично имплементират
изброените интерфейси
Интерфейси
class Dog : Animal, ISoundMaker
{
// Неявно имплементиране
public void MakeSound()
{
Console.WriteLine("Woof!");
}
}
class Motorcycle : ISoundMaker, IMobileObject
{
// Явно имплементиране
void ISoundMaker.MakeSound()
{
Console.WriteLine("Vroom!");
}
// Неявно имплементиране
public void MoveTo(Point location)
{
// преместване
}
}
• Имплементиране на интерфейси
– В декларацията на типа, след
родителския клас (в случай че има
такъв), се изброяват интерфейсите,
които той имплементира
– Неявно имплементиране на членове
– Явно имплементиране на членове
• Полезно, когато няколко интерфейса
декларират един и същи член с различно
предназначение
• Полезно и когато самият клас се налага да
декларира същият член, но с различно
предназнчение
Имплементиране на интерфейси - демо
// Демонстрация
Интерфейси
// Деклариране на променлива от интерфейсен тип
ISoundMaker soundMaker;
// Присвояване на екземпляри на различни класове
soundMaker = new Dog();
soundMaker.MakeSound();
soundMaker = new Motorcycle();
soundMaker.MakeSound();
// Преобразуване на типове към друг интерфейс
IMobileObject mobileObject =
soundMaker as IMobileObject;
if (mobileObject != null)
mobileObject.MoveTo(point);
// Преобразуване на типове към клас
if (soundMaker is Animal)
{
Animal animal = (Animal)soundMaker;
// ...
}
• Употреба на интерфейси
– Не могат да бъдат създавани екземпляри
на интерфейси
– Служат за типове на променливи,
параметри и изрази
– Неявно и явно преобразуване на типове към
интерфейс – сходни правила с upcasting и
downcasting за класове
– Явно преобразуване на типове от
интерфейс към клас/структура – сходни
правила с downcasting за класове
– Проверка за съвместимост на типове –
оператори as и is
– Явно имплементираните членове могат да
бъдат достъпени единствено през
референция, чийто тип е съответният
интерфейс
Употреба на интерфейси - демо
// Демонстрация
Интерфейси
• Приложения на интерфейсите
– Обединяват сходни групи от формално поведение, без да се
ангажират с реализацията му
– Позволяват гъвкавост на типовете данни
• Един и същи обект може да се разглежда като коренно различни неща от
отделни фрагменти на програмата (с помощта на различни интерфейси)
• Коренно различни обекти могат да се разглеждат като еднотипни от гледна
точка на фрагмент на програмата
– Полезни са за т.нар. слабо обвързване (loose coupling), което
улеснява поддръжката и тестването на софтуера
– Някои вградени интерфейси позволяват употребата на специални
синтактични конструкции в C#
Интерфейсите IEnumerable и IEnumerator
• Интерфейсите IEnumerable и IEnumerator
– Декларирани в пространството от имена System.Collections
– Служат за обхождане на колекция от елементи един по един (без
връщане назад)
– Използват се от конструкцията за цикъл foreach
– Ако потребителски тип данни имплементира IEnumerable,
елементите в неговите екземпляри автоматично могат да бъдат
обхождани с foreach
Имплементиране на IEnumerable - демо
// Демонстрация
Интерфейсът IDisposable
• Интерфейсът IDisposable
– Деклариран в пространството от имена System
– Служи за детерминистично освобождаване на заети ресурси след
причключване на работата с обект, който го имплементира
• например: файл от файловата система
– Garbage Collector освобождава заетите ресурси от обект, който
вече не се използва, в неопределен момент
– Декларира единствен метод: void Dispose()
– Конструкцията using в C# приема обект, имплементиращ
IDisposable, и блок с операции
• Автоматично се изпълнява методът Dispose() след приключването на
операциите в блока
• Методът Dipose() ще бъде изпълнен, дори ако настъпи грешка при
изпълнението на операциите в блока
Интерфейсът IDisposable
string fileName = @"C:Prices.txt";
// Отваряне на файл за четене
// StreamReader имплементира IDisposable
using (StreamReader reader =
new StreamReader(fileName))
{
// Прочитане съдържанието на файла и
// изпечатване на конзолата ред по ред
while (!reader.EndOfStream)
{
string line = reader.ReadLine();
Console.WriteLine(line);
}
// След излизане от този блок, файлът
// автоматично ще бъде затворен
}
• Конструкцията using
– Ключова дума using
– Израз от тип IDisposable, заграден в
кръгли скоби
• Може да бъде декларация на променлива с
инициализация
– Блок с операции
Имплементиране на IDisposable и конструкцията using
- демо
// Демонстрация
Шаблонни типове
• Какво е „шаблонен тип“ (generic type)?
– Клас, структура или интерфейс
– При декларирането му се посочват един или повече типови
параметри
– Типовите параметри могат да се използват вместо действителни
типове данни в декларацията му
– От шаблонния тип се създават шаблонни екземпляри, като всеки
типов параметър се замества с действителен тип данни
– Шаблонните екземпляри са пълноправни типове данни
– Шаблонните типове сами по себе си не са пълноправни типове
данни: реално се прилагат единствено екземплярите им
Шаблонни типове
• Типови параметри
– Идентификатори
• Еднобуквени – T, U, V…
• По-дълги – с представка T
– Изброяват се в ъглови скоби непосредствено след наименованието
на типа в декларацията му
– Могат да се използват вместо действителен тип данни в
декларацията на типа
Шаблонни типове
// Клас за стек от произволен тип елементи
class Stack<T>
{
// Вътрешен масив за елементите
private readonly T[] _items;
// Текущ брой на елементите в стека
private int _count;
public Stack(int capacity)
{
_items = new T[capacity];
_count = 0;
}
public void Push(T item)
{
_items[_count++] = item;
}
public T Pop()
{
return _items[--_count];
}
}
• Деклариране на шаблонни типове
– Модификатор за достъп
(незадължителен)
– class, struct или interface
– Наименование
– Списък от типови параметри в ъглови
скоби
– Родителски класове и
имплементирани интерфейси
– Блок с декларации на членове
Деклариране на шаблонни типове - демо
// Демонстрация
Шаблонни типове
• Шаблонни екземпляри
– Шаблонен екземпляр се създава, като след наименованието на
шаблонния тип във фигурни скоби се изброяват действителни
типове данни, съответстващи на типовите параметри
– Указаният действителен тип замества всички срещания на
съответния му типов параметър
– Възможно е влагане на шаблонни екземпляри (един шаблонен
екземпляр замества типов параметър при създаването на
шаблонен екземпляр на друг шаблонен тип)
Шаблонни типове
// Стек от цели числа
Stack<int> stack1 = new Stack<int>(100);
stack1.Push(0);
stack1.Push(3);
int x = stack1.Pop();
// Стек от дати
Stack<DateTime> stack2 =
new Stack<DateTime>(20);
stack2.Push(DateTime.Today);
stack2.Push(DateTime.Now);
DateTime date = stack2.Pop();
• Използване на шаблонни
екземпляри
– Наименование на шаблонния тип
– Списък от действителни типове данни в
ъглови скоби
– Шаблонният екземпляр може да бъде
използван навсякъде, където се очаква
тип данни
• Променливи
• Параметри
• Тип на връщания резултат на методи
• Извиквания на конструктори
• Явни преобразувания на типове
• Обръщения към статични членове
Използване на шаблонни екземпляри - демо
// Демонстрация
Шаблонни типове
• Ограничения на типовите параметри
– В декларацията на шаблонен тип могат да се наложат ограничения
върху действителните типове, които могат да го заместят
– При създаване на шаблонен екземпляр, действителният тип за
съответния типов параметър трябва да удовлетворява
ограничението
– В противен случай компилаторът предизвиква грешка
– Налагането на ограничения позволява по-специализирани
операции с данните, чийто тип е типовия параметър, в
декларациите на членове в шаблонния тип
• Извикване на конструктор
• Присвояване на null
• Използване на метод, деклариран в някой клас/интерфейс
Шаблонни типове
• Ограничения на типовите параметри
– Да е референтен тип данни – ключова дума class
– Да е нереферентен тип данни – ключова дума struct
– Да има конструктор без параметри – new()
– Да наследява клас – наименование на класа
– Да наследява/имплементира интерфейс – наименование на
интерфейса
– Да наследява/имплементира действителния тип, съответстващ на
друг типов параметър – наименование на типовия параметър
– Ограниченията могат да се комбинират: действителният тип трябва
едновременно да удовлетворява всички указани ограничения
Шаблонни типове
class SortedList<T> : IEnumerable
where T : IComparable
{
// ...
}
class Expression<T>
where T : struct
{
// ...
}
interface IAnimalCollection<T> : IEnumerable
where T : Animal
{
// ...
}
• Ограничения на типови параметри
– Наименование на типа и списък от
типови параметри
– Списък от родителски/
имплементирани типове
(незадължително)
– Нула или повече декларации за
ограничения на типов параметър
• Ключова дума where
• Типов параметър
• Двоеточие
• Списък от ограничения, разделени със
запетаи
– Блок с декларации на членове
Ограничения на типови параметри - демо
// Демонстрация
Шаблонни типове
• Приложения на шаблонните типове
– Строго типизирани структури данни, които не са обвързани с
конкретен тип данни на елементите: списъци, опашки, стекове,
множества, асоциативни масиви, дървета и т.н.
– Класове и алгоритми, които имат еднотипна реализация,
независеща от конкретния тип на съответните обекти или техни
фрагменти
Шаблонни методи
• Какво е „шаблонен метод“ (generic method)?
– Сходен с шаблонен тип
– В декларацията на метода се посочват един или повече типови
параметри
– Типовите параметри могат да се използват вместо действителни
типове данни в декларацията на метода (параметри, тип на
връщания резултат, локални променливи и т.н.)
– При използването на шаблонен метод задължително се указват
действителни типове данни, които да заместят типовите параметри
– Възможно е да се наложат ограничения на типовите параметри
Шаблонни методи
static class ConversionHelper
{
public static T ConvertTo<T>(object value)
{
// ...
}
}
static class SortingHelper
{
public static void BubbleSort<T>(T[] array)
where T : IComparable
{
// ...
}
}
• Деклариране на шаблонни методи
– Модификатор за достъп
(незадължителен)
– static, abstract, virtual, override
(незадължителни)
– Тип на връщания резултат или void
– Наименование
– Списък от типови параметри в ъглови
скоби
– Списък от параметри в кръгли скоби
– Нула или повече ограничения
(синтаксис като при шаблонните
типове)
– Блок с операции (тяло)
Деклариране на шаблонни методи - демо
// Демонстрация
Шаблонни методи
// Използване на шаблонен метод
int x = 15;
double y =
ConversionHelper.ConvertTo<double>(x);
char[] characters = new char[100];
// ...
// Използване на шаблонен метод с явно
// указване на действителните типове данни
SortingHelper.BubbleSort<char>(characters);
// Използване на шаблонен метод без явно
// указвване на действителните типове данни
SortingHelper.BubbleSort(characters);
• Използване на шаблонни методи
– Наименование на шаблонния метод
– Списък от действителни типове данни в
ъглови скоби
– Действителните типове данни трябва да
удовлетворяват поставените
ограничения
– Списък от аргументи в кръгли скоби
– Възможно е списъкът с действителни
типове данни да се пропусне, ако
компилаторът може да ги отгатне от
типовете на аргументите, с които е
извикан методът
Използване на шаблонни методи - демо
// Демонстрация
Шаблонни методи
• Приложения на шаблонните методи
– Строго типизирани алгоритми, които не са обвързани с конкретен
тип данни на аргументите
– Алгоритми, които оперират с шаблонни типове данни
– Реализиране на шаблонно поведение в тип данни, който не е
шаблонен
Вградени шаблонни колекции
• Вградени интерфейси за строго типизирани колекции
– Декларирани в пространство от имена System.Collections.Generic
– IEnumerable<T> - строго типизирана изброима колекция
– ICollection<T> - строго типизирана колекция с информация за
текущия брой елементи и възможност за добавяне и премахване
на елементи; наследява IEnumerable<T>
– IList<T> - строго типизирана колекция с възможност за достъпване и
промяна на елементите по индекс; наследява ICollection<T>
– IDictionary<TKey, TValue> - строго типизиран асоциативен масив с
информация за текущия брой елементи и възможност за
достъпване, добавяне и премахване на елементи по уникалните им
ключове
Вградени шаблонни колекции
• Вградени реализации на строго типизирани колекции
– Декларирани в пространство от имена System.Collections.Generic
– List<T> - строго типизиран списък, реализиран вътрешно чрез масив;
имплементира IList<T>
– LinkedList<T> - строго типизиран (двойно) свързан списък;
имплементира ICollection<T>
– Stack<T> - строго типизиран стек; имплементира IEnumerable<T>
– Queue<T> - строго типизирана опашка; имплементира
IEnumerable<T>
– HashSet<T> - строго типизирано множество без повторения;
имплементира ICollection<T>
– Dictionary<TKey, TValue> - строго типизиран асоциативен масив;
имплементира IDictionary<TKey, TValue>
Вградени шаблонни колекции - демо
// Демонстрация
Задачи за упражнение
• Преработете програмата „Геометричните фигури“ от
предишните упражнения, така че да се възползвате от
новите възможности на езика, за които научихте:
– Създайтеабстрактен базов клас GeometryObject с характеристика
име, виртуален метод за въвеждане от клавиатурата и абстрактен
метод за генериране на случайни стойности на характеристиките
– Заменете класовете Object2D и Object3D с интерфейсите
IObject2D със стойства периметър и лице и IObject3D със свойства
пълна повърхнина и обем
– Използвайте List<GeometryObject> за съхранение на списъка от
геометрични обекти в класа GeometryStore
– Реализирайте логика за извеждане само на равнинните фигури и
само на тримерните тела (използвайки съответните интерфейси)
Задачи за упражнение
• Преработете програмата „Ролева игра“ от предишните
упражнения, така че да се възползвате от абстракция,
интерфейси и шаблони
• Реализирайте шаблонен тип за строго типизирана
приоритетна опашка:
– При добавяне на елемент в опашката се указва приоритет (цяло
число); елементът се добавя непосредствено след последния
елемент с по-висок или равен приоритет
– От опашката се винаги се вади само челният елемент
– Може да се прочете челният елемент, без да бъде изваден
– Имплементирайте интерфейса IEnumerable<T>, като изброявате
елементите в посока от челния елемент към края на опашката
Задачи за упражнение
• Реализирайте статични шаблонни методи за сортиране на
аргумент от тип IList<T> чрез следните алгоритми:
– Метод на мехурчето
– Метод на пряката селекция
– Сортиране чрез вмъкване
– Quicksort
• Реализирайте структура за рационално число Rational
– Презапишете операторите за аритметични операции и сравнение
за него
– Предефинирайте методите ToString() и Equals()
– Имплементирайте интерфейсите IComparable,
IComparable<Rational>, IEquatable<Rational> и IConvertible
Въпроси?
Благодаря!
• Александър Далемски
– sasho@david.bg
– Skype: musasho
– https://facebook.com/adalemski
• ДАВИД академия
– acad@david.bg
– http://acad.david.bg/
– @david_academy
– https://facebook.com/DavidAcademy

More Related Content

PPTX
Курс по уеб програмиране (2015), занятие №3 - JavaScript (част 1/2)
PPTX
Училищен курс по програмиране на C# (2013/2014), занятие №7
PPTX
Училищен курс по програмиране на C# (2013/2014), занятие №11
PPTX
Училищен курс по програмиране на C# (2013/2014), занятие №9
PPTX
Училищен курс по програмиране на C# (2013/2014), занятие №10
PPTX
Училищен курс по програмиране на C# (2013/2014), занятие №13
PPTX
Училищен курс по програмиране на C# (2013/2014), занятие №8
PPTX
Курс по информационни технологии (2013) - 1. Desktop приложения. Windows Form...
Курс по уеб програмиране (2015), занятие №3 - JavaScript (част 1/2)
Училищен курс по програмиране на C# (2013/2014), занятие №7
Училищен курс по програмиране на C# (2013/2014), занятие №11
Училищен курс по програмиране на C# (2013/2014), занятие №9
Училищен курс по програмиране на C# (2013/2014), занятие №10
Училищен курс по програмиране на C# (2013/2014), занятие №13
Училищен курс по програмиране на C# (2013/2014), занятие №8
Курс по информационни технологии (2013) - 1. Desktop приложения. Windows Form...

What's hot (16)

PPTX
Курс по програмиране на C# 2013 - 2. Конзолен вход и изход. Условни преходи. ...
PPTX
Курс по уеб програмиране (2015), занятие №1 - HTML
PPTX
Училищен курс по програмиране на C# (2013/2014), занятие №14
PPTX
Курс по програмиране на C# 2013 - 1. Въведение в компютърното програмиране и C#
PPTX
Курс по програмиране на C# 2013 - 8. Полиморфизъм. Абстракция. Шаблони. Вград...
PPTX
Училищен курс по програмиране на C# (2013/2014), занятие №2
PPTX
Курс по уеб програмиране (2015), занятие №4 - JavaScript (част 2/2)
PPTX
Курс по уеб програмиране (2014), занятие №3 - JavaScript (част 1/2)
PPTX
Курс по уеб програмиране (2015), занятие №2 - CSS
PPTX
Училищен курс по програмиране на C# (2013/2014), занятие №4
PPTX
Курс по програмиране на C# 2013 - 7. Свойства. Индексатори. Наследяване. Изкл...
PPTX
Курс по уеб програмиране (2014), занятие №4 - JavaScript (част 2/2)
PDF
PPTX
Курс по уеб програмиране (2014), занятие №2 - CSS
PPTX
Acceptance testing with Selenium 2 and PHPUnit
PPTX
Училищен курс по програмиране на C# (2013/2014), занятие №3
Курс по програмиране на C# 2013 - 2. Конзолен вход и изход. Условни преходи. ...
Курс по уеб програмиране (2015), занятие №1 - HTML
Училищен курс по програмиране на C# (2013/2014), занятие №14
Курс по програмиране на C# 2013 - 1. Въведение в компютърното програмиране и C#
Курс по програмиране на C# 2013 - 8. Полиморфизъм. Абстракция. Шаблони. Вград...
Училищен курс по програмиране на C# (2013/2014), занятие №2
Курс по уеб програмиране (2015), занятие №4 - JavaScript (част 2/2)
Курс по уеб програмиране (2014), занятие №3 - JavaScript (част 1/2)
Курс по уеб програмиране (2015), занятие №2 - CSS
Училищен курс по програмиране на C# (2013/2014), занятие №4
Курс по програмиране на C# 2013 - 7. Свойства. Индексатори. Наследяване. Изкл...
Курс по уеб програмиране (2014), занятие №4 - JavaScript (част 2/2)
Курс по уеб програмиране (2014), занятие №2 - CSS
Acceptance testing with Selenium 2 and PHPUnit
Училищен курс по програмиране на C# (2013/2014), занятие №3
Ad

Similar to Училищен курс по програмиране на C# (2013/2014), занятие №12 (20)

PPTX
Курс по програмиране за напреднали (2012) - 1. Обектно-ориентирано програмира...
PPT
Svetlin Nakov - .NET Framework Overview
PPT
Nakov - .NET Framework Overview + Security
PPTX
Училищен курс по програмиране на C# (2013/2014), занятие №1
PPTX
Курс по програмиране на C# 2013 - 6. Обектно-ориентирано програмиране. Класов...
PPTX
.NET/C#_1
ODP
Mozllla Labs presentation
PPT
Nakov High Quality Code
PPT
High Quality Code Introduction
PPTX
Курс по информационни технологии (2013) - 4. XML, XSD, XML в .NET Framework
PPT
Macromedia flash lesson1
PPT
Introduction To Object Oriented Design and UML
PPTX
[Dev.bg] CI from scratch with Jenkins
PDF
1. vb sredi za programirane. ide. gui
PDF
1. vb sredi za programirane. ide. gui
DOCX
Курс по програмиране за напреднали (2012) - 4. Desktop приложения. Windows Forms
PPT
Основи на програмирането за андроид
PPTX
Java kurs
PPTX
Курс по програмиране на C# 2013 - 3. Функции и методи. Рекурсия
DOC
18 operatori i funkcii
Курс по програмиране за напреднали (2012) - 1. Обектно-ориентирано програмира...
Svetlin Nakov - .NET Framework Overview
Nakov - .NET Framework Overview + Security
Училищен курс по програмиране на C# (2013/2014), занятие №1
Курс по програмиране на C# 2013 - 6. Обектно-ориентирано програмиране. Класов...
.NET/C#_1
Mozllla Labs presentation
Nakov High Quality Code
High Quality Code Introduction
Курс по информационни технологии (2013) - 4. XML, XSD, XML в .NET Framework
Macromedia flash lesson1
Introduction To Object Oriented Design and UML
[Dev.bg] CI from scratch with Jenkins
1. vb sredi za programirane. ide. gui
1. vb sredi za programirane. ide. gui
Курс по програмиране за напреднали (2012) - 4. Desktop приложения. Windows Forms
Основи на програмирането за андроид
Java kurs
Курс по програмиране на C# 2013 - 3. Функции и методи. Рекурсия
18 operatori i funkcii
Ad

More from DAVID Academy (10)

PPTX
Курс по уеб програмиране (2014), занятие №1 - HTML
DOCX
Училищен курс по програмиране на C# (2013/2014) - Помагало
DOCX
Училищен курс по програмиране на C# (2013/2014) - Упражнения
PPTX
Курс по информационни технологии (2013) - 5. HTTP & Web Services
PPTX
Курс по информационни технологии (2013) - 3. ADO.NET, LINQ to SQL
PPTX
Курс по информационни технологии (2013) - 2. Бази данни. Системи за управлени...
PPTX
Курс по информационни технологии (2013) - 0. Представяне
DOCX
Курс по информационни технологии (2013) - Помагало
DOCX
Курс по програмиране на C# (2013) - Упражнения
PPTX
Курс по програмиране на C# 2013 - 9. Делегати. Събития. Ламбда функции
Курс по уеб програмиране (2014), занятие №1 - HTML
Училищен курс по програмиране на C# (2013/2014) - Помагало
Училищен курс по програмиране на C# (2013/2014) - Упражнения
Курс по информационни технологии (2013) - 5. HTTP & Web Services
Курс по информационни технологии (2013) - 3. ADO.NET, LINQ to SQL
Курс по информационни технологии (2013) - 2. Бази данни. Системи за управлени...
Курс по информационни технологии (2013) - 0. Представяне
Курс по информационни технологии (2013) - Помагало
Курс по програмиране на C# (2013) - Упражнения
Курс по програмиране на C# 2013 - 9. Делегати. Събития. Ламбда функции

Училищен курс по програмиране на C# (2013/2014), занятие №12

  • 1. 2013 Курс по програмиране на C# Занятие №12 Полиморфизъм (част 2): Абстракция. Интерфейси. Шаблонни типове и методи
  • 2. Съдържание • Абстрактни класове и членове • Интерфейси • Интерфейсите IEnumerable и IEnumerator • Интерфейсът IDisposable • Шаблонни типове • Шаблонни методи • Вградени шаблонни колекции
  • 3. Полиморфизъм • Полиморфизъм - преговор – Основен принцип на ООП – Еднотипна работа с разнотипни данни – Обобщаване на възможности, но с различна реализация – Обединяване на сходни функционалности в нещо общо – Гъвкав и лесен начин за поддръжка на кода – Статичен (compile-time) и динамичен (run-time) – Презаписване на членове и оператори – Виртуални членове и предефиниране
  • 4. Абстракция • Какво е „абстрактен клас “? – Не може да бъде инстанциран директно – Описва поведение, общо за йерархията от наследени класове – Не се ангажира с пълната реализация на поведението – Използва се като събирателен тип данни за променливи, параметри и изрази
  • 5. Абстракция abstract class Shape2D { // Декларации на членове } abstract class Animal { // Декларации на членове } • Деклариране на абстрактни класове – Модификатор за достъп (незадължителен) – Ключова дума abstract – Наименование на класа – Родителски клас (незадължителен) – Блок с декларации на членове
  • 6. Деклариране на абстрактни класове - демо // Демонстрация
  • 7. Абстракция • Какво е „абстрактен член“? – Виртуален член на клас – При декларирането му не е описано тяло (блок от операции) – Описва сигнатурата на члена, но не и неговата реализация – Представлява поведение, което от формална гледна точка е сходно между различните подкласове, но няма обща реализация в общия родителски клас – Класът, в който е деклариран, задължително трябва да бъде маркиран като абстрактен – По време на изпълнение на програмата винаги се изпълнява реализацията в някой от наследените класове
  • 8. Абстракция abstract class Shape2D { // Абстрактен метод public abstract void InputFromConsole(); // Абстрактно свойство // (само за четене) public abstract double Area { get; } public virtual void PrintToConsole() { // Използване на абстрактното // свойство Area Console.WriteLine( "Area: {0}", Area); } } • Деклариране и употреба на абстрактни членове – Ключовата дума virtual след модификатора за достъп се заменя с ключовата дума abstract – Блокът/блоковете с операции на члена се заменят с „;“ – Употребяват се идентично на обикновени членове
  • 9. Деклариране и употреба на абстрактни членове - демо // Демонстрация
  • 10. Абстракция • Наследяване на абстрактни класове – Наследеният клас трябва да предефинира всички абстрактни членове на абстрактния родителски клас – В противен случай, самият той трябва да бъде маркиран като абстрактен – При предефиниране на абстрактен член не може да бъде преизползвана реализацията в родителския клас (тъй като няма такава) – Веднъж предефиниран, съответният член е възможно, но не е задължително да бъде предефиниран в наследените класове надолу в йерархията
  • 11. Наследяване на абстрактни класове - демо // Демонстрация
  • 12. Абстракция • Приложения на абстракцията – Предотвратяване на създаването на екземпляри от родителски (не достатъчно конкретен) клас, който не е предназначен за самостоятелна употреба – Обединяване на сходното формално поведение, когато няма нищо общо във вътрешната реализация – Възможност за комбиниране на общи членове с реализация с такива без – Недостатък: не позволява комбиниране на отделни групи от функционалности на произволен принцип, поради липсата на множествено наследяване
  • 13. Интерфейси • Какво е „интерфейс“? – Тип данни – Декларира единствено поведение – Не описва реализация на поведението – Сходен с напълно абстрактен клас (клас без полета, всички членове на който са абстрактни) – Може да се разглежда като „договор“ между тип данни, който реализира декларираното поведение, и код, който го използва – Интерфейсите се имплементират от класове/структури – имплементиращият тип е длъжен да предостави имплементация на съответните членове (може и абстрактна) – Един клас/структура може да имплементира няколко интерфейса (множествено наследяване?)
  • 14. Интерфейси • Интерфейси в C# – Референтни типове данни – Не може да бъде създаден екземпляр на интерфейс – Могат да декларират единствено методи, свойства и индексатори – Всички членове са с публична видимост – Всеки интерфейс може да наследява един или няколко други интерфейса; при това той автоматично получава членовете, декларирани в родителските интерфейси – Интерфейс може да наследява единствено интерфейси – Прието е да се именуват с представка I (от interface)
  • 15. Интерфейси // Интерфейс за обекти, които издават звуци public interface ISoundMaker { void MakeSound(); } // Интерфейс за обекти, които могат да се придвижват public interface IMobileObject { void MoveТо(Point location); } // Интерфейс за обекти, които могат да се печатат // на конзолата interface IPrintableObject { void PrintToConsole(); } // Интерфейс за равнинни фигури interface IPlanarShape : IPrintableObject { double Perimeter { get; } double Area { get; } } • Деклариране на интерфейси – Модификатор за достъп (незадължителен) – Ключова дума interface – Наименование на интерфейса – Двоеточие – Списък от родителски интерфейси (незадължителен) – Блок с декларации на членове • Методи, свойства и индексатори • Без модификатори за достъп • Блоковете с операции се заменят с „;“ • Без ключови думи virtual и abstract
  • 16. Деклариране на интерфейси - демо // Демонстрация
  • 17. Интерфейси • Имплементиране на интерфейси в C# – При деклариране на клас или структура може да бъдат указани един или повече интерфейси, които типът данни имплементира – В декларацията на типа данни трябва да бъдат имплементирани всички членове, декларирани от съответните интерфейси – Неявно имплементиране на член – деклариране на член с публична видимост и със същата сигнатура по стандартния начин – Явно имплементиране на член – деклариране на член със същата сигнатура, като наименованието му се префиксира с наименованието на съответния интерфейс и „.“
  • 18. Интерфейси • Имплементиране на интерфейси в C# – Възможно е членовете да са абстрактни, така че да бъдат предефинирани в наследен клас – Възможно е член на интерфейса да бъде неявно имплементиран от публичен член със същата сигнатура, който е бил деклариран в родителски клас – Всички наследени от текущият типове автоматично имплементират изброените интерфейси
  • 19. Интерфейси class Dog : Animal, ISoundMaker { // Неявно имплементиране public void MakeSound() { Console.WriteLine("Woof!"); } } class Motorcycle : ISoundMaker, IMobileObject { // Явно имплементиране void ISoundMaker.MakeSound() { Console.WriteLine("Vroom!"); } // Неявно имплементиране public void MoveTo(Point location) { // преместване } } • Имплементиране на интерфейси – В декларацията на типа, след родителския клас (в случай че има такъв), се изброяват интерфейсите, които той имплементира – Неявно имплементиране на членове – Явно имплементиране на членове • Полезно, когато няколко интерфейса декларират един и същи член с различно предназначение • Полезно и когато самият клас се налага да декларира същият член, но с различно предназнчение
  • 20. Имплементиране на интерфейси - демо // Демонстрация
  • 21. Интерфейси // Деклариране на променлива от интерфейсен тип ISoundMaker soundMaker; // Присвояване на екземпляри на различни класове soundMaker = new Dog(); soundMaker.MakeSound(); soundMaker = new Motorcycle(); soundMaker.MakeSound(); // Преобразуване на типове към друг интерфейс IMobileObject mobileObject = soundMaker as IMobileObject; if (mobileObject != null) mobileObject.MoveTo(point); // Преобразуване на типове към клас if (soundMaker is Animal) { Animal animal = (Animal)soundMaker; // ... } • Употреба на интерфейси – Не могат да бъдат създавани екземпляри на интерфейси – Служат за типове на променливи, параметри и изрази – Неявно и явно преобразуване на типове към интерфейс – сходни правила с upcasting и downcasting за класове – Явно преобразуване на типове от интерфейс към клас/структура – сходни правила с downcasting за класове – Проверка за съвместимост на типове – оператори as и is – Явно имплементираните членове могат да бъдат достъпени единствено през референция, чийто тип е съответният интерфейс
  • 22. Употреба на интерфейси - демо // Демонстрация
  • 23. Интерфейси • Приложения на интерфейсите – Обединяват сходни групи от формално поведение, без да се ангажират с реализацията му – Позволяват гъвкавост на типовете данни • Един и същи обект може да се разглежда като коренно различни неща от отделни фрагменти на програмата (с помощта на различни интерфейси) • Коренно различни обекти могат да се разглеждат като еднотипни от гледна точка на фрагмент на програмата – Полезни са за т.нар. слабо обвързване (loose coupling), което улеснява поддръжката и тестването на софтуера – Някои вградени интерфейси позволяват употребата на специални синтактични конструкции в C#
  • 24. Интерфейсите IEnumerable и IEnumerator • Интерфейсите IEnumerable и IEnumerator – Декларирани в пространството от имена System.Collections – Служат за обхождане на колекция от елементи един по един (без връщане назад) – Използват се от конструкцията за цикъл foreach – Ако потребителски тип данни имплементира IEnumerable, елементите в неговите екземпляри автоматично могат да бъдат обхождани с foreach
  • 25. Имплементиране на IEnumerable - демо // Демонстрация
  • 26. Интерфейсът IDisposable • Интерфейсът IDisposable – Деклариран в пространството от имена System – Служи за детерминистично освобождаване на заети ресурси след причключване на работата с обект, който го имплементира • например: файл от файловата система – Garbage Collector освобождава заетите ресурси от обект, който вече не се използва, в неопределен момент – Декларира единствен метод: void Dispose() – Конструкцията using в C# приема обект, имплементиращ IDisposable, и блок с операции • Автоматично се изпълнява методът Dispose() след приключването на операциите в блока • Методът Dipose() ще бъде изпълнен, дори ако настъпи грешка при изпълнението на операциите в блока
  • 27. Интерфейсът IDisposable string fileName = @"C:Prices.txt"; // Отваряне на файл за четене // StreamReader имплементира IDisposable using (StreamReader reader = new StreamReader(fileName)) { // Прочитане съдържанието на файла и // изпечатване на конзолата ред по ред while (!reader.EndOfStream) { string line = reader.ReadLine(); Console.WriteLine(line); } // След излизане от този блок, файлът // автоматично ще бъде затворен } • Конструкцията using – Ключова дума using – Израз от тип IDisposable, заграден в кръгли скоби • Може да бъде декларация на променлива с инициализация – Блок с операции
  • 28. Имплементиране на IDisposable и конструкцията using - демо // Демонстрация
  • 29. Шаблонни типове • Какво е „шаблонен тип“ (generic type)? – Клас, структура или интерфейс – При декларирането му се посочват един или повече типови параметри – Типовите параметри могат да се използват вместо действителни типове данни в декларацията му – От шаблонния тип се създават шаблонни екземпляри, като всеки типов параметър се замества с действителен тип данни – Шаблонните екземпляри са пълноправни типове данни – Шаблонните типове сами по себе си не са пълноправни типове данни: реално се прилагат единствено екземплярите им
  • 30. Шаблонни типове • Типови параметри – Идентификатори • Еднобуквени – T, U, V… • По-дълги – с представка T – Изброяват се в ъглови скоби непосредствено след наименованието на типа в декларацията му – Могат да се използват вместо действителен тип данни в декларацията на типа
  • 31. Шаблонни типове // Клас за стек от произволен тип елементи class Stack<T> { // Вътрешен масив за елементите private readonly T[] _items; // Текущ брой на елементите в стека private int _count; public Stack(int capacity) { _items = new T[capacity]; _count = 0; } public void Push(T item) { _items[_count++] = item; } public T Pop() { return _items[--_count]; } } • Деклариране на шаблонни типове – Модификатор за достъп (незадължителен) – class, struct или interface – Наименование – Списък от типови параметри в ъглови скоби – Родителски класове и имплементирани интерфейси – Блок с декларации на членове
  • 32. Деклариране на шаблонни типове - демо // Демонстрация
  • 33. Шаблонни типове • Шаблонни екземпляри – Шаблонен екземпляр се създава, като след наименованието на шаблонния тип във фигурни скоби се изброяват действителни типове данни, съответстващи на типовите параметри – Указаният действителен тип замества всички срещания на съответния му типов параметър – Възможно е влагане на шаблонни екземпляри (един шаблонен екземпляр замества типов параметър при създаването на шаблонен екземпляр на друг шаблонен тип)
  • 34. Шаблонни типове // Стек от цели числа Stack<int> stack1 = new Stack<int>(100); stack1.Push(0); stack1.Push(3); int x = stack1.Pop(); // Стек от дати Stack<DateTime> stack2 = new Stack<DateTime>(20); stack2.Push(DateTime.Today); stack2.Push(DateTime.Now); DateTime date = stack2.Pop(); • Използване на шаблонни екземпляри – Наименование на шаблонния тип – Списък от действителни типове данни в ъглови скоби – Шаблонният екземпляр може да бъде използван навсякъде, където се очаква тип данни • Променливи • Параметри • Тип на връщания резултат на методи • Извиквания на конструктори • Явни преобразувания на типове • Обръщения към статични членове
  • 35. Използване на шаблонни екземпляри - демо // Демонстрация
  • 36. Шаблонни типове • Ограничения на типовите параметри – В декларацията на шаблонен тип могат да се наложат ограничения върху действителните типове, които могат да го заместят – При създаване на шаблонен екземпляр, действителният тип за съответния типов параметър трябва да удовлетворява ограничението – В противен случай компилаторът предизвиква грешка – Налагането на ограничения позволява по-специализирани операции с данните, чийто тип е типовия параметър, в декларациите на членове в шаблонния тип • Извикване на конструктор • Присвояване на null • Използване на метод, деклариран в някой клас/интерфейс
  • 37. Шаблонни типове • Ограничения на типовите параметри – Да е референтен тип данни – ключова дума class – Да е нереферентен тип данни – ключова дума struct – Да има конструктор без параметри – new() – Да наследява клас – наименование на класа – Да наследява/имплементира интерфейс – наименование на интерфейса – Да наследява/имплементира действителния тип, съответстващ на друг типов параметър – наименование на типовия параметър – Ограниченията могат да се комбинират: действителният тип трябва едновременно да удовлетворява всички указани ограничения
  • 38. Шаблонни типове class SortedList<T> : IEnumerable where T : IComparable { // ... } class Expression<T> where T : struct { // ... } interface IAnimalCollection<T> : IEnumerable where T : Animal { // ... } • Ограничения на типови параметри – Наименование на типа и списък от типови параметри – Списък от родителски/ имплементирани типове (незадължително) – Нула или повече декларации за ограничения на типов параметър • Ключова дума where • Типов параметър • Двоеточие • Списък от ограничения, разделени със запетаи – Блок с декларации на членове
  • 39. Ограничения на типови параметри - демо // Демонстрация
  • 40. Шаблонни типове • Приложения на шаблонните типове – Строго типизирани структури данни, които не са обвързани с конкретен тип данни на елементите: списъци, опашки, стекове, множества, асоциативни масиви, дървета и т.н. – Класове и алгоритми, които имат еднотипна реализация, независеща от конкретния тип на съответните обекти или техни фрагменти
  • 41. Шаблонни методи • Какво е „шаблонен метод“ (generic method)? – Сходен с шаблонен тип – В декларацията на метода се посочват един или повече типови параметри – Типовите параметри могат да се използват вместо действителни типове данни в декларацията на метода (параметри, тип на връщания резултат, локални променливи и т.н.) – При използването на шаблонен метод задължително се указват действителни типове данни, които да заместят типовите параметри – Възможно е да се наложат ограничения на типовите параметри
  • 42. Шаблонни методи static class ConversionHelper { public static T ConvertTo<T>(object value) { // ... } } static class SortingHelper { public static void BubbleSort<T>(T[] array) where T : IComparable { // ... } } • Деклариране на шаблонни методи – Модификатор за достъп (незадължителен) – static, abstract, virtual, override (незадължителни) – Тип на връщания резултат или void – Наименование – Списък от типови параметри в ъглови скоби – Списък от параметри в кръгли скоби – Нула или повече ограничения (синтаксис като при шаблонните типове) – Блок с операции (тяло)
  • 43. Деклариране на шаблонни методи - демо // Демонстрация
  • 44. Шаблонни методи // Използване на шаблонен метод int x = 15; double y = ConversionHelper.ConvertTo<double>(x); char[] characters = new char[100]; // ... // Използване на шаблонен метод с явно // указване на действителните типове данни SortingHelper.BubbleSort<char>(characters); // Използване на шаблонен метод без явно // указвване на действителните типове данни SortingHelper.BubbleSort(characters); • Използване на шаблонни методи – Наименование на шаблонния метод – Списък от действителни типове данни в ъглови скоби – Действителните типове данни трябва да удовлетворяват поставените ограничения – Списък от аргументи в кръгли скоби – Възможно е списъкът с действителни типове данни да се пропусне, ако компилаторът може да ги отгатне от типовете на аргументите, с които е извикан методът
  • 45. Използване на шаблонни методи - демо // Демонстрация
  • 46. Шаблонни методи • Приложения на шаблонните методи – Строго типизирани алгоритми, които не са обвързани с конкретен тип данни на аргументите – Алгоритми, които оперират с шаблонни типове данни – Реализиране на шаблонно поведение в тип данни, който не е шаблонен
  • 47. Вградени шаблонни колекции • Вградени интерфейси за строго типизирани колекции – Декларирани в пространство от имена System.Collections.Generic – IEnumerable<T> - строго типизирана изброима колекция – ICollection<T> - строго типизирана колекция с информация за текущия брой елементи и възможност за добавяне и премахване на елементи; наследява IEnumerable<T> – IList<T> - строго типизирана колекция с възможност за достъпване и промяна на елементите по индекс; наследява ICollection<T> – IDictionary<TKey, TValue> - строго типизиран асоциативен масив с информация за текущия брой елементи и възможност за достъпване, добавяне и премахване на елементи по уникалните им ключове
  • 48. Вградени шаблонни колекции • Вградени реализации на строго типизирани колекции – Декларирани в пространство от имена System.Collections.Generic – List<T> - строго типизиран списък, реализиран вътрешно чрез масив; имплементира IList<T> – LinkedList<T> - строго типизиран (двойно) свързан списък; имплементира ICollection<T> – Stack<T> - строго типизиран стек; имплементира IEnumerable<T> – Queue<T> - строго типизирана опашка; имплементира IEnumerable<T> – HashSet<T> - строго типизирано множество без повторения; имплементира ICollection<T> – Dictionary<TKey, TValue> - строго типизиран асоциативен масив; имплементира IDictionary<TKey, TValue>
  • 49. Вградени шаблонни колекции - демо // Демонстрация
  • 50. Задачи за упражнение • Преработете програмата „Геометричните фигури“ от предишните упражнения, така че да се възползвате от новите възможности на езика, за които научихте: – Създайтеабстрактен базов клас GeometryObject с характеристика име, виртуален метод за въвеждане от клавиатурата и абстрактен метод за генериране на случайни стойности на характеристиките – Заменете класовете Object2D и Object3D с интерфейсите IObject2D със стойства периметър и лице и IObject3D със свойства пълна повърхнина и обем – Използвайте List<GeometryObject> за съхранение на списъка от геометрични обекти в класа GeometryStore – Реализирайте логика за извеждане само на равнинните фигури и само на тримерните тела (използвайки съответните интерфейси)
  • 51. Задачи за упражнение • Преработете програмата „Ролева игра“ от предишните упражнения, така че да се възползвате от абстракция, интерфейси и шаблони • Реализирайте шаблонен тип за строго типизирана приоритетна опашка: – При добавяне на елемент в опашката се указва приоритет (цяло число); елементът се добавя непосредствено след последния елемент с по-висок или равен приоритет – От опашката се винаги се вади само челният елемент – Може да се прочете челният елемент, без да бъде изваден – Имплементирайте интерфейса IEnumerable<T>, като изброявате елементите в посока от челния елемент към края на опашката
  • 52. Задачи за упражнение • Реализирайте статични шаблонни методи за сортиране на аргумент от тип IList<T> чрез следните алгоритми: – Метод на мехурчето – Метод на пряката селекция – Сортиране чрез вмъкване – Quicksort • Реализирайте структура за рационално число Rational – Презапишете операторите за аритметични операции и сравнение за него – Предефинирайте методите ToString() и Equals() – Имплементирайте интерфейсите IComparable, IComparable<Rational>, IEquatable<Rational> и IConvertible
  • 54. Благодаря! • Александър Далемски – [email protected] – Skype: musasho – https://facebook.com/adalemski • ДАВИД академия – [email protected] – http://acad.david.bg/ – @david_academy – https://facebook.com/DavidAcademy