C#. Проблемы множественного наследования.
Интерфейсы
Синтаксис объявления интерфейса:
Общие сведения об интерфейсе
Выбор между интерфейсом и наследованием
Отличие интерфейса и абстрактного класса
Реализация интерфейса
Пример
Неявная реализация интерфейса
Явная реализация интерфейса
Пример явной реализации интерфейса
Результат работы программы
Операция is
Операция as
Итоги
Пример
215.80K
Category: programmingprogramming

Интерфейсы. Проблемы множественного наследования

1. C#. Проблемы множественного наследования.

Интерфейсы.

2. Интерфейсы

• Интерфейс (interface) – соглашение, определяющее поведение
объекта.
• В нем задается набор абстрактных методов, свойств и индексаторов,
которые должны быть реализованы в производных классах.
• В объекте допустимо реализовать несколько интерфейсов, а один и
тот же интерфейс можно реализовать в нескольких классах.
• Любые объекты, в которых реализован некоторый интерфейс могут
взаимодействовать через него.
• Основная идея использования интерфейса состоит в том, чтобы к
объектам таких классов можно было обращаться одинаковым
образом.
• Каждый класс может определять элементы интерфейса по-своему. Так
достигается полиморфизм: объекты разных классов по-разному
реагируют на вызовы одного и того же метода.

3. Синтаксис объявления интерфейса:

[ атрибуты ] [ спецификаторы ]
interface имя [ : предки ]
тело_интерфейса [ ; ]
Пример:
class Человек : IОбразованный, IВодитель
interface IОбразованный {Читат(); Писать();}
interface IВодитель {Завести(); Повернуть();
Затормозить()}

4. Общие сведения об интерфейсе

• Интерфейс может наследовать свойства
нескольких интерфейсов, в этом случае предки
перечисляются через запятую.
• Тело интерфейса составляют абстрактные
методы, шаблоны свойств и индексаторов, а
также события.
• Интерфейс не может содержать константы,
поля, операции, конструкторы, деструкторы,
типы и любые статические элементы.

5. Выбор между интерфейсом и наследованием

• Если некий набор действий имеет смысл только для
какой-то конкретной иерархии классов,
реализующих эти действия разными способами,
уместнее задать этот набор в виде виртуальных
методов абстрактного базового класса иерархии.
• То, что работает в пределах иерархии одинаково,
предпочтительно полностью определить в базовом
классе.
• Интерфейсы чаще используются для задания общих
свойств классов, относящихся к различным
иерархиям.

6. Отличие интерфейса и абстрактного класса

• элементы интерфейса по умолчанию имеют спецификатор
доступа public и не могут иметь спецификаторов,
заданных явным образом;
• интерфейс не может содержать полей и обычных
методов — все элементы интерфейса должны быть
абстрактными;
• класс, в списке предков которого задается интерфейс,
должен определять все его элементы, в то время как
потомок абстрактного класса может не переопределять
часть абстрактных методов предка (в этом случае
производный класс также будет абстрактным);
• класс может иметь в списке предков несколько
интерфейсов, при этом он должен определять все их
методы.

7. Реализация интерфейса

• В C# поддерживается одиночное наследование для
классов и множественное — для интерфейсов. Это
позволяет придать производному классу свойства
нескольких базовых интерфейсов, реализуя их по
своему усмотрению.
• Сигнатуры методов в интерфейсе и реализации должны
полностью совпадать.
• Для реализуемых элементов интерфейса в классе
следует указывать спецификатор public.
• К этим элементам можно обращаться как через объект
класса, так и через объект типа соответствующего
интерфейса.

8. Пример

interface IPlayer. // Интерфейс Игрок,
//наследующие классы реализуют его по разному:
{
void play();
}
public class Ball: IPlayer
{
public void play()
{
Console.WriteLine("Игра в мяч");
}
}

9.

public class Guitar: IPlayer
{
public void play()
{
Console.WriteLine("Игра на
гитаре");
}
}

10. Неявная реализация интерфейса

interface IPlayer{
void play();
}
class Ball: Iplayer{
public void play(){……..}; // обязательно public!
}

11. Явная реализация интерфейса

class Ball: IPlayer{
void Iplayer. play() {…………….}
//тут спецификатор public отсутствует, потому что
попытка написать тут public карается
};

12.

При явной реализации вызов возможен лишь при явном
приведении.
Явная реализация интерфейса означает, что вызов метода
интерфейса может происходить только через ссылку на
интерфейс, но не может происходить через ссылку на класс,
реализующий интерфейс.
Перед вызовом интерфейсного метода необходимо явно
преобразовать ссылку на объект реализующего класса к
ссылке на интерфейс. Концепция явной реализации полезна,
например, при конфликте имен между унаследованными
интерфейсами.
В C# реализованные методы интерфейсов считаются по
умолчанию «sealed» - запечатанными. В наследниках они
перекрываются.

13. Пример явной реализации интерфейса

interface I1
{
void Method();
}
interface I2
{
int Method();
}
class Test : I1, I2
{
public void Method()
{
Console.WriteLine("Реализация интерфейса I1");
}

14.

int I2.Method() // РЕАЛИЗУЕМ интерфейс явно
{
Console.WriteLine("Реализация интерфейса I2");
return 5;
}
}
class Program
{
static void Main(string[] args)
{
Test t = new Test();
t.Method();// реализация метода I1.Method() в классе Test
((I1)t).Method();// реализация метода I1.Method() в классе Test
((I2)t).Method();// реализация метода I2.Method() в классе Test
} // приводим к типу интерфейса явно реализованному
}// наш объект класса Test
}

15. Результат работы программы

16. Операция is

При работе с объектом через объект типа интерфейса бывает
необходимо убедиться, что объект поддерживает данный
интерфейс.
Проверка выполняется с помощью бинарной операции is. Она
определяет, совместим ли текущий тип объекта, находящегося
слева от ключевого слова is, с типом, заданным справа.
Результат операции равен true, если объект можно преобразовать к
заданному типу, и false в противном случае. Операция обычно
используется в следующем контексте:
if ( объект is тип )
{
// выполнить преобразование "объекта" к "типу"
// выполнить действия с преобразованным объектом
}

17. Операция as

Используется для проверки поддерживает ли данный тип
тот или иной интерфейс, если да, то операция as выполняет
преобразование к заданному типу, а если это невозможно,
формирует результат null:
static void Act( object A )
{
IAction Actor = A as IAction;
if ( Actor != null ) Actor.Draw();
}
Обе рассмотренные операции применяются как к
интерфейсам, так и к классам.

18. Итоги

Интерфейсы на С# обеспечивают разработку классов, у
которых могут быть общие функции, но при этом они не
являются частями одной и той же иерархии классов.
Интерфейсы играют особую роль в разработке на С#,
поскольку С# не поддерживает множественное
наследование. Чтобы совместно использовать методы и
свойства, классы могут реализовывать несколько
интерфейсов. Операторы is и asпозволяют определить,
реализован ли конкретный интерфейс конкретным
объектом, что помогает предотвратить ошибки,
связанные с использованием членов интерфейса.
Наконец, явное именование членов и сокрытие имен
позволяют управлять реализацией интерфейса и
избежать многих ошибок.

19. Пример

public interface Apartment
{
double Area{get; set;}
void GetInfo();
}

20.

public class ThreeRoom: Apartment
{
private double area; //площадь
public int Area
{
get
{
return area;
}
set
{ area = value;
}
}
public void GetInfo()
{
Console.WriteLine("Это трехкомнатная квартира”);
}
}

21.

public interface Luxury
{
int Price{get; set;}
void GetInfo();
}

22.

public class SuperThree: ThreeRoom, Apartment, Luxury
{
private double area; //
private int price; //цена
public double Area
{
get
{
return area;
}
set
{
area = value;
}
}
public void GetInfo()
{
Console.WriteLine("Это роскошная 3-х комнатная квартира".);
}
public int Price
{
get
{
return price;
}
set
{
price = value;
}
}

23.

void ThreeRoom.GetInfo()
{
Console.WriteLine("Это квартира".);
}
void Apartment.GetInfo()
{
Console.WriteLine("Эта квартира стоит
кучу денег!".);
}

24.

static void Main(string[] args)
{
SuperThree ob = new SuperThree();
ob.Price = 1000000;
ob.Area = 450;
if (ob is Apartment)
{
Apartment tmp = (Apartment)ob;
tmp.GetInfo();
}
if (ob is Luxury)
{
Luxury tmp2 = (Luxury)ob;
tmp2.GetInfo();
}
Console.ReadLine();
}

25.

Использование стандартных интерфейсов
Рассмотрим интерфейс ICloneable
Если объект реализует данный интерфейс, значит его
(объект) можно копировать.
IEnumerable, IEnumerator- дают возможность
простамтривать содержимое объекта с помощью
конструкции foreach.
Массивы в C# работают с foreach благодаря тому что
тип Array реализует интерфейсы IEnumerable,
IEnumerator.
interface Icomparable
{
int ComparTo(object);
}

26.

class Money:ICloneable, IComparable
{
int som;
public Money()
{
som = 0;
}
public Money(int s)
{
som = s;
}

27.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ForLecture
{
public int Som
{
set{som=value;}
get{return som;}
}
public override string ToString()
{
return som.ToString();
}
public object Clone()
{
return new Money(this.Som);
}

28.

int IComparable.CompareTo(object o)
{
Money tmp = (Money)o;
if (this.som > tmp.som) return 1;
if (this.som == tmp.som)
return 0;
else
return -1;
}
}

29.

class Program
{
static void Main(string[] args)
{
Console.WriteLine("Исходные данные");
Money ob1=new Money(100);
Console.WriteLine(ob1);
Money ob2 = new Money(200);
Console.WriteLine(ob2);
ob2 = (Money)ob1.Clone();

30.

Console.WriteLine("После клонирования");
Console.WriteLine(ob1);
Console.WriteLine(ob2);
Console.WriteLine("Изменяем свойства ob2.Som=500 ");
ob2.Som = 500;
Console.WriteLine(ob1);
Console.WriteLine(ob2);

31.

Console.WriteLine("Изменяем свойства ob1.Som=500
ob2.Som=1500 ");
ob1.Som = 500;
ob2.Som = 1500;
Console.WriteLine(ob1);
Console.WriteLine(ob2);
}
}
}

32.

Использование реализации интерфейса IComparable
Console.WriteLine(" Массив объектов до сортировки");
Money[] mas = new Money[4];
mas[0] = new Money(4000);
mas[1] = new Money(2000);
mas[2] = new Money(5000);
mas[3] = new Money(1000);
for (int i = 0; i < 4; i++)
Console.WriteLine(mas[i]);
Array.Sort(mas);
Console.WriteLine("Сортировка массива объектов");
for (int i = 0; i < 4; i++)
Console.WriteLine(mas[i]);
Console.ReadLine();

33.

class Money:ICloneable<Money>
{
int som;
int key;
public Money()
{
som = 0;

public int CompareTo(Money o)
{
return key-o.key;
}
}
static void Main(string[] args)
{
List<Money> list=new List<Money>();
for(int i=0;i<10;i++)
list.Add(new Money());
………..
list.Sort();
}

34.

Клонирование объектов
Клонирование – создание копии объекта.
Копия объекта называется клоном
Виды клонирования
При присваивании одного объекта ссылочного типа другому копируется
ссылка, а не сам объект.
Если необходимо скопировать в другую область памяти поля объекта, можно
Воспользоваться методом MemberwiseClone, который объект наследует от
kласса object. При этом объекты, на которые указывают поля объекта, в свою
Очередь являющиеся ссылками, не копируются. Это называется поверхностным
Клонированием.
Для создания полностью независимых объектов необходимо глубокое клонирование,
Когда в памяти создается дубликат всего дерева объектов.
Алгоритм глубокого клонирования является достаточно сложным, поскольку требует
рекурсивного обхода всех ссылок объекта и отслеживания циклических зависимостей.
Объект, имеющий собственные алгоритмы клонирования, должен объявляться как
наследник интерфейса IClonable и переопределять его единственныый метод Clone.

35.

Виды клонирования
1) Присваивание b=a 2)поверхностное клонирование 3) глубокое клонирование
English     Русский Rules