Слайд 1Системное программирование
для Microsoft.NET на языке C#
Лекция 5
Оцоков Шамиль
Алиевич,
Московский энергетический институт,
Email: otsokovShA@mpei.ru
Слайд 2Полиморфизм
Полиморфизм – это различная реализация однотипных действий. Классическая фраза, которая
коротко объясняет полиморфизм – «Один интерфейс, множество реализаций»
Приведу примеры
из жизни. В автомобилях есть рулевое колесо. Это колесо является интерфейсом между водителем и автомобилем, который позволяет поворачивать автомобиль.
Механическая реализация руля у автомобилей может быть разная, но при этом результат получается одинаковым – колесо вправо – автомобиль вправо, и наоборот.
Слайд 3Полиморфизм
Например, есть класс Геометрическая Фигура, и в нем объявлен метод
Draw(), который будет рисовать фигуру. От этого класса наследуются классы
Треугольник, Четырёхугольник, Пятиугольник. В них реализуется метод для рисования (понятно, что реализация рисования каждой фигуры разная). В итоге мы можем создать объекты этих классов, и у всех будет метод Draw(), который будет рисовать соответствующую фигу
Слайд 4Полиморфизм
Полиморфизм позволяет :
писать более абстрактные, расширяемые программы,
- один и
тот же код используется для объектов разных классов,
улучшается читабельность
кода.
избавляет разработчика от написания, чтения и отладки множества if-else/switch-case конструкций.
Слайд 5Абстрактные классы
Вот правила об абстрактных классах:
• Вы не можете создать экземпляр
абстрактного класса
• Вы не можете объявить абстрактный метод вне
абстрактного класса
Виртуальный метод – это метод, который МОЖЕТ быть переопределен в классе-наследнике. Такой метод может иметь стандартную реализацию в базовом классе.
Абстрактный метод – это метод, который ДОЛЖЕН быть реализован в классе-наследнике. При этом, абстрактный метод не может иметь своей реализации в базовом классе (тело пустое), в отличии от виртуального.
Переопределение метода – это изменение реализации метода, установленного как виртуальный (в классе наследнике метод будет работать отлично от базового класса).
Слайд 6Абстрактные классы
В качестве системы, предоставляющей тот самый интерфейс, в программировании
может выступать класс и интерфейс. Здесь мы поговорим о классах.
Есть класс, в нем объявлен виртуальный или абстрактный метод. От этого класса наследуются еще несколько классов, и в каждом из них по-разному реализуется тот самый виртуальный/абстрактный метод. Получается, объекты этих классов имеют метод с одинаковым именем, но с разной реализацией. В этом и есть полиморфизм.
Слайд 7Абстрактные классы
public abstract class myBase
{
// Если вы унаследованы от этого
класса, вы должны реализовать этот метод. обратите внимание, у нас
нет тела метода здесь
public abstract void YouMustImplement();
// Если вы унаследованы от этого класса, вы можете изменить поведение, но не обязаны
public virtual void YouCanOverride()
{
….
}
}
Слайд 8Абстрактные классы
public class MyBase
{
Это не скомпилируется, потому что
вы не можете иметь абстрактный метод в неабстрактном классе
public abstract void YouMustImplement();
}
abstract class Figure
{
// абстрактный метод для получения периметра
public abstract float Perimeter();
// абстрактный метод для получения площади
public virtual int area()
{
Console.WriteLine("Parent class area :");
return 0;
}
public Figure ()
{
}
}
Слайд 9Пример полиморфизма
public class Shape
{
// A few example members
public int X { get; private set; }
public int Y { get; private set; }
public int Height { get; set; }
public int Width { get; set; }
// Virtual method
public void Draw()
{
Console.WriteLine("Performing base class drawing tasks");
}
}
class Circle : Shape
{
public override void Draw()
{
// Code to draw a circle...
Console.WriteLine("Drawing a circle");
base.Draw();
}
}
Слайд 10Абстрактные классы
class Rectangle : Shape
{
public override void Draw()
{
// Code to draw a
rectangle...
Console.WriteLine("Drawing a rectangle");
base.Draw();
}
}
class Triangle : Shape
{
int color;
public override void Draw()
{
// Code to draw a triangle...
Console.WriteLine("Drawing a triangle");
base.Draw();
}
}
Слайд 11Абстрактные классы
static void Main(string[] args)
{
// Полиморфизм
в работе №1: прямоугольник, треугольник и круг
// все
могут использоваться везде, где ожидается Shape.
// требуется, потому что существует неявное преобразование из производного
// класс к его базовому классу.
var shapes = new List
{
new Rectangle(),
new Triangle(),
new Circle()
};
// Полиморфизм № 2: виртуальный метод Draw
// вызывается для каждого из производных классов, а не для
// базового класса.
foreach (var shape in shapes)
{
shape.Draw();
}
}
Слайд 12Интерфейсы
Интерфейс представляет ссылочный тип, который определяет набор методов и свойств,
но не реализует их.
Для определения интерфейса используется ключевое слово interface.
Как правило, названия интерфейсов в C# начинаются с заглавной буквы I
interface IMovable
{
void Move();
}
В данном случае интерфейс определяет метод Move, который будет представлять некоторое передвижение.
Все его члены - методы и свойства не имеют модификаторов доступа, но фактически по умолчанию доступ public
В целом интерфейсы могут определять следующие сущности:
Методы, Свойства, Индексаторы, События
Однако интерфейсы не могут определять статические члены, переменные, константы.
Слайд 13Интерфейсы
// реализация интерфейса в классе
class Person : IMovable
{
public
void Move()
{
Console.WriteLine("Человек идет");
}
}
// реализация интерфейса в классе
Class Car : IMovable
{
public void Move()
{
Console.WriteLine("Машина едет");
}
}
Слайд 14Интерфейсы
static void Action(IMovable movable)
{
movable.Move();
}
static void Main(string[] args)
{
Person person = new Person();
Car car = new Car();
Action(person);
Action(car);
Console.Read();
}
Слайд 15Абстрактные классы или интерфейсы
Когда следует использовать абстрактные классы:
• Если надо определить
общий функционал для
родственных объектов
• Если мы проектируем довольно большую
функциональную единицу, которая содержит много
базового функционал
• Если нужно, чтобы все производные классы на всех
уровнях наследования имели некоторую общую
реализацию.
Когда следует использовать интерфейсы:
• Если нам надо определить функционал для группы
разрозненных объектов, которые могут быть никак не связаны
между собой.
• Если мы проектируем небольшой функциональный тип
Слайд 16Абстрактные классы или интерфейсы
Допустим, у нас есть система транспортных средств:
легковой автомобиль, автобус, трамвай, поезд и т.д. Поскольку данные объекты
являются родственными, мы можем выделить у них общие признаки, то в данном случае можно использовать абстрактные классы:
public abstract class Vehicle
{
public abstract void Move();
}
public class Car : Vehicle
{
public override void Move()
{
Console.WriteLine("Машина едет");
}
}
…
Слайд 17Абстрактные классы или интерфейсы
Например, мы можем добавить самолеты, лодки. Возможно,
также мы добавим лошадь - животное, которое может также выполнять
роль транспортного средства.
Вобщем получается довольно широкий круг объектов, которые связаны только тем, что являются транспортным средством и должны реализовать некоторый метод Move(), выполняющий перемещение.
Так как объекты малосвязанные между собой, то для определения общего для всех них функционала лучше определить интерфейс
Слайд 19Доработка №1 программы Copy
public class Copier
{
//не забудьте сбросить этот флаг
public
static bool ptFlag = false;
public static void Copy()
{
int c;
while((c=(ptFlag ?
Flash() .Read(): Keyboard.Read())) != -1)
Printer.Write(c);
}
}
Если программа хочет вызвать Copy для чтения с флешки, то долж-
на сначала установить для переменной ptFlag значение true. А после завершения программы Copy нужно сбросить этот флаг, иначе следующий
обратившийся будет читать с флешки, а не с клавиатуры. Чтобы напомнить программистам о необходимости сбрасывать флаг, вы включили комментарий.
<усл. Выр> ? <блок№1>:<блок №2>
If (усл. Выр)
{блок№1}
else
{блок №2}
Слайд 20Доработка №2 программы Copy
public class Copier
{
//не забудьте сбросить эти флаги
public
static bool ptFlag = false;
public static bool ptFlag2 = false;
public
static void Copy()
{
…
}
}
А что делать если еще надо добавить считывание с DVD?
Слайд 21Доработка №2 программы Copy
public class Copier
{
//не забудьте сбросить эти флаги
public
static bool ptFlag = false;
public static bool ptFlag2 = false;
public
static void Copy()
{
…
}
}
А что делать если еще надо добавить считывание с DVD Rom?
Слайд 22Модификация программы Copy
public class Copier
{
//не забудьте сбросить эти флаги
public
static bool ptFlag = false;
public static bool ptFlag2 = false;
public
static void Copy()
{
…
}
}
В данном случае команда следовала принципу открытости/закрыто-
сти. Он требует проектировать модули так, чтобы их можно было расширять без модификации.
Столкнувшись с таким отсутствием эластичности, гибкие разработчики
сразу поняли, что направление зависимости от модуля Copy к устройству
ввода следует инвертировать, воспользовавшись принципом инверсии
зависимости
Слайд 24Принципы
гибкой разработки
- Высшим приоритетом считать удовлетворение пожеланий заказчика по-
средством поставки
полезного программного обеспечения в сжатые сроки
- Не игнорировать изменение требований
-
В процессе разработки предоставлять промежуточные версии ПО часто,
с интервалом от пары недель до пары месяцев
- Заказчики и разработчики должны работать совместно на протяжении
всего проекта.
- Проекты должны воплощать в жизнь целеустремленные люди.
- Самый эффективный и продуктивный метод передачи информации ко-
манде разработчиков и обмена мнениями внутри нее – разговор лицом
к лицу
- Работающая программа – основной показатель прогресса в проекте
- Непрестанное внимание к техническому совершенству и качественному
проектированию повышает отдачу от гибких технологий
- Самые лучшие архитектуры, требования и проекты выдают самооргани-
зующиеся команды
- Команда должна регулярно задумываться над тем, как стать еще более
эффективной, а затем соответственно корректировать и подстраивать свое
поведение.
Слайд 25Разработка через тестирование
SVN
Git,
… TortoiseSVN
Слайд 26Разработка через тестирование
Вид тестирования, при котором на соответствие требований проверяется
интеграция модулей, их взаимодействие между собой, а также интеграция подсистем
в одну общую систему. Для интеграционного тестирования используются компоненты, уже проверенные с помощью модульного тестирования, которые группируются в множества. Данные множества проверяются в соответствии с планом тестирования, составленным для них, а объединяются они через свои интерфейсы.
Слайд 27Компонент ListBox
Все элементы списка входят в свойство Items, которое представляет собой
коллекцию. Для добавления нового элемента в эту коллекцию, а значит
и в список, надо использовать метод Add, например:
listBox1.Items.Add("Новый элемент");.
Слайд 28Компонент ListBox
Можно добавить сразу несколько элементов, например, массив. Для этого
используется метод AddRange:
string[] countries = { "Бразилия", "Аргентина", "Чили", "Уругвай", "Колумбия"
};
listBox1.Items.AddRange(countries);
Слайд 29Компонент ListBox
В отличие от простого добавления вставка производится по определенному
индексу списка с помощью метода Insert:
listBox1.Items.Insert(1, "Парагвай");
В данном случае вставляем
элемент на вторую позицию в списке, так как отсчет позиций начинается с нуля.
listBox1.Items.Remove("Чили");
удалить элемент по его индексу в списке, используется метод RemoveAt:
listBox1.Items.RemoveAt(1);
очистить сразу весь список, применив метод Clear:
listBox1.Items.Clear();
Слайд 30Компонент ListBox
Используя индекс элемента, можно сам элемент в списке. Например,
получим первый элемент списка:
string firstElement = listBox1.Items[0];
Метод Count позволяет определить
количество элементов в списке:
int number = listBox1.Items.Count();
Слайд 31Компонент ListBox
• SelectedIndex: возвращает или устанавливает
номер выделенного элемента списка. Если
выделенные элементы отсутствуют, тогда свойство имеет значение -1
• SelectedIndices: возвращает или
устанавливает коллекцию выделенных элементов в виде набора их индексов
• SelectedItem: возвращает или устанавливает текст выделенного элемента
• SelectedItems: возвращает или устанавливает выделенные элементы в виде коллекции
Слайд 32Компонент ListBox
По умолчанию список поддерживает выделение одного элемента. Чтобы добавить
возможность выделения нескольких элементов, надо установить у его свойства SelectionMode
значение MultiSimple.
Чтобы выделить элемент програмно, надо применить метод SetSelected(int index, bool value), где index - номер выделенного элемента. Если второй параметр - value имеет значение true, то элемент по указанному индексу выделяется, если false, то выделение наоборот скрывается:
Слайд 33Компонент ListBox
Событие SelectedIndexChanged
Из всех событий элемента ListBox надо отметить в
первую очередь событие SelectedIndexChanged, которое возникает при изменении выделенного элемента:
void listBox1_SelectedIndexChanged(object
sender, EventArgs e)
{
string selectedCountry = listBox1.SelectedItem.ToString();
MessageBox.Show(selectedCountry);
}
Слайд 34Свойства
Кроме обычных методов в языке C# предусмотрены специальные методы доступа,
которые называют свойства. Они обеспечивают простой доступ к полям классов
и структур, узнать их значение или выполнить их установку.
Стандартное описание свойства имеет следующий синтаксис:
[модификатор_доступа] возвращаемый_тип произвольное_название
{
// код свойства
}
Слайд 35Свойства
class Person
{
private string name;
public string
Name
{
get
{
return name;
}
set
{
name = value;
}
}
}
Слайд 36Свойства
class Dog
{
private int
age;
public int Age
{
get
{
// геттер, блок который возвращает возраст (значение
// типа int
return this.age;
}
set
{ // сеттер value –
this.age = value;
}
}
}
Слайд 37Свойства
Dog dog = new Dog();
dog.Age = 20;
Console.WriteLine(doc.Age);