27
Толстиков Никита [email protected] Пользовательские типы данных в C# 05.07.2022 1 Введение

Net Framework и С#, весна 2015: Собственные классы

Embed Size (px)

Citation preview

Page 1: Net Framework и С#, весна 2015: Собственные классы

Толстиков Никита[email protected]

Пользовательские типы данных в C#

02.05.2023 1Введение

Page 2: Net Framework и С#, весна 2015: Собственные классы

План лекции

• Классы и интерфейсы• Наследование• Пример реализации

стандартных интерфейсов• Принцип подстановки

Лисков(LSP)

02.05.2023 Толстиков Никита 2План лекции

Page 3: Net Framework и С#, весна 2015: Собственные классы

Классы

• Ссылочный тип данных• Может содержать поля,

методы, свойства, события• Позволяет обеспечить

инкапсуляцию с помощью модификаторов доступа

02.05.2023 Толстиков Никита 3Классы

public class Rectangle{}

Page 4: Net Framework и С#, весна 2015: Собственные классы

Классы

02.05.2023 Толстиков Никита 4Классы

public class Rectangle{ private int myHeight; private int myWidth;

public Rectangle(int width, int height) { /* ... */ }

public int CalculateArea() { /* ... */ }

public int Height { get { /* ... */ } set { /* ... */ } } public int Width { get { /* ... */ } set { /* ... */ } }}

Page 5: Net Framework и С#, весна 2015: Собственные классы

Наследование

02.05.2023 Толстиков Никита 5Наследование

• Можно обращаться к членам базового класса через производный класс

class Ogr : Monster{

public string Color { get; } public void Jump() { }}

Page 6: Net Framework и С#, весна 2015: Собственные классы

Наследование конструкторов

02.05.2023 Толстиков Никита 6Наследование

• Для вызова базового конструктора используется ключевое слово base

public Ogr(string color) : base(100){

Color = color;}public Ogr()

: this(“White") { }

...Ogr ogr = new Ogr("Green");

public Ogr(string color) // ошибка { Color = color; }

Page 7: Net Framework и С#, весна 2015: Собственные классы

Переопределение поведения

02.05.2023 Толстиков Никита 7Наследование

• Ключевые слова virtual и override позволяют переопределить поведение базового класса:class Monster

{...

public virtual void Kill(Monster m) { m.Die(); }}

class Ogr : Monster{ public override void Kill(Monster other) { Console.WriteLine("Aaargh!"); base.Kill(other); }}

Page 8: Net Framework и С#, весна 2015: Собственные классы

Переопределение поведения

02.05.2023 Толстиков Никита 8Наследование

• Если забыть про override:

• То огр заговорит, если указатель на него типа Ogr:

class Ogr : Monster{

public void Kill(Monster m) {...}...

}

Monster ogr1 = new Ogr("green");Ogr ogr2 = new Ogr("red");

ogr1.Kill(ogr1);ogr2.Kill(ogr2);

Page 9: Net Framework и С#, весна 2015: Собственные классы

Переопределение поведения

02.05.2023 Толстиков Никита 9Наследование

• Warning:

• Если вы и правда хотели скрыть метод то воспользуйтесь ключевым словом new

Warning 1'HelloWorld.Ogr.Kill(HelloWorld.Monster)' hides inherited member 'HelloWorld.Monster.Kill(HelloWorld.Monster)'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.

Page 10: Net Framework и С#, весна 2015: Собственные классы

Абстрактный класс

02.05.2023 Толстиков Никита 10Наследование

• Нельзя создать объект абстрактного класса

• Можно реализовать часть методов• Может иметь конструкторы

internal abstract class Monster{

... public virtual void Kill(Monster m) { m.Die();

}public abstract int Height { get; }

public abstract void Die();}

Page 11: Net Framework и С#, весна 2015: Собственные классы

Абстрактный класс

02.05.2023 Толстиков Никита 11Наследование

• Для наследования от абстрактного класса нужно переопределить все методы помеченные как abstract

class Ogr : Monster{

public override int Height { get { return 100; } } public override void Die() { Health = 0; }}

Page 12: Net Framework и С#, весна 2015: Собственные классы

Sealed классы

02.05.2023 Толстиков Никита 12Наследование

• Ключевое слово sealed запрещает наследование

• Все value-типы sealed. Т.е. нельзя наследоваться от struct и примитивных типов (int, string, double и т.д.)

sealed class BestClass{}

Page 13: Net Framework и С#, весна 2015: Собственные классы

Интерфейсы

02.05.2023 Толстиков Никита 13Интерфейсы

• Интерфейс – контракт на реализацию действия

• Может содержать: свойства, методы, индексаторы и события

interface IMonster{

int Id { get; }string Name { get; }int Health { get; set; }

void Die();void Kill(IMonster monster);

string this[int index] { get; }}

Page 14: Net Framework и С#, весна 2015: Собственные классы

Интерфейсы

02.05.2023 Толстиков Никита 14Интерфейсы

• Реализация интерфейса:class Monster : IMonster{

public int Id { get; }public string Name { get; set; }public int Health { get; set; }

public void Die(){

Health = 0;}public void Kill(IMonster m){

m.Die();}

private readonly string[] myKnownWords = {"Argh", "Life for Aiure"};public string this[int i]{

get { return myKnownWords[i]; }}

}

Page 15: Net Framework и С#, весна 2015: Собственные классы

Интерфейсы

02.05.2023 Толстиков Никита 15Интерфейсы

• Объект интерфейса нельзя создать

• Интерфейс может быть типом параметра

• Приведение к интерфейсу неявное:IMonster m1 = new Monster();Monster m2 = new Monster();

bool b = m2 is IMonster; //true m1 = m2;m1.Kill(m2);

Page 16: Net Framework и С#, весна 2015: Собственные классы

Реализация интерфейсов

02.05.2023 Толстиков Никита 16Интерфейсы

• IDisposable – интерфейс для безопасной работы с ресурсами. Применяется в конструкции using

• IComparable – задает порядок сортировки объектов типа

interface IComparable{ int CompareTo(object obj);}

Page 17: Net Framework и С#, весна 2015: Собственные классы

Реализация интерфейсов

02.05.2023 Толстиков Никита 17Интерфейсы

• IComparable состоит из метода CompareTo который возвращает число:–Меньше ноля, если порядок this < obj– Ноль, если порядок this равен obj– Больше ноля, если порядок this > obj

• Большинство классов и структур FCL реализуют этот интерфейс

• Переиспользуйте стандартные реализации

Page 18: Net Framework и С#, весна 2015: Собственные классы

Реализация интерфейсов

02.05.2023 Толстиков Никита 18Интерфейсы

class BigNumber : IComparable{ ... public int CompareTo(object obj) { if (obj == null) return 0;

if (!(obj is BigNumber)) throw new ArgumentException("Object is not BigNumber");

BigNumber other = (BigNumber) obj; return this.myValue.CompareTo(other.myValue); }}

Page 19: Net Framework и С#, весна 2015: Собственные классы

Реализация интерфейсов

02.05.2023 Толстиков Никита 19Интерфейсы

• Интерфейс IClonable имеет единственный метод Clone()

public class CloneableOgr : Ogr, ICloneable { public CloneableOgr(string color) : base(color) { }

public object Clone() { CloneableOgr result = new CloneableOgr(Color); return result; } }

Page 20: Net Framework и С#, весна 2015: Собственные классы

Реализация интерфейсов

02.05.2023 Толстиков Никита 20Интерфейсы

О IEnumerable, ICollection, IQueryable, ISerializable и т.д. будет рассказано на следующих лекциях

НЕ ПРОПУСТИТЕ!!!

Page 21: Net Framework и С#, весна 2015: Собственные классы

Интерфейсы

02.05.2023 Толстиков Никита 21Интерфейсы

• Явная(explicit) реализация интерфейса:interface ILeft

{void Move();

}

interface IRight{

void Move();}

class MoveableOject : ILeft, IRight{

void ILeft.Move() { }void IRight.Move() { }

}

Page 22: Net Framework и С#, весна 2015: Собственные классы

Интерфейсы

02.05.2023 Толстиков Никита 22Интерфейсы

• При явной реализации вызвать метод можно только от типа интерфейса:

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

MoveableOject obj = new MoveableOject();

((ILeft)obj).Move();((IRight)obj).Move();

Page 23: Net Framework и С#, весна 2015: Собственные классы

LSP

02.05.2023 Толстиков Никита 23LSP

• LSP(Liskov substitution principle) – функции, использующие базовый тип должны корректно работать на производных типах

• Т.е. подкласс не должен менять поведение неожиданно для пользователя

Page 24: Net Framework и С#, весна 2015: Собственные классы

Пример

02.05.2023 Толстиков Никита 24LSP

class Rectangle { public Rectangle(int width, int height) { Width = width; Height = height; } public int Height { get; set; } public int Width { get; set; } public int Area { get { return Height * Width; } } }

Page 25: Net Framework и С#, весна 2015: Собственные классы

Пример

02.05.2023 Толстиков Никита 25LSP

class Square : Rectangle { public override int Width { get { return base.Width; } set { base.Width = value; base.Height = value; } } public override int Height { get { return base.Height; } set { base.Height = value; base.Width = value; } } }

Page 26: Net Framework и С#, весна 2015: Собственные классы

Пример

02.05.2023 Толстиков Никита 26LSP

Rectangle rectangle = new Square();rectangle.Width = 10;rectangle.Height = 5;Console.WriteLine(rectangle.Area); //Результат: 25

• Тем самым пользователь не поймет почему результат 25, а не 50

• Следствие: наследование не должно применяться для переиспользования кода, если это нарушает LSP

Page 27: Net Framework и С#, весна 2015: Собственные классы

The End

02.05.2023 Толстиков Никита 27Собственные типы