Тема № 4

65
Тема №4 Об’єктні властивості C#

description

Тема № 4. Об ’ єктні властивості C#. ООП у C#: найбільш помітні особливості. C# – повністю об ’ єктно-орієнтована мова . Всі змінні – об ’ єкти . Немає множинного спадкування класів. Доступ до екземплярів Reference Type здійснюється виключно через указники на них. - PowerPoint PPT Presentation

Transcript of Тема № 4

Page 1: Тема № 4

Тема №4

Об’єктні властивості C#

Page 2: Тема № 4

ООП у C#: найбільш помітні особливості1. C# – повністю об’єктно-орієнтована мова.2. Всі змінні – об’єкти.3. Немає множинного спадкування класів.4. Доступ до екземплярів Reference Type

здійснюється виключно через указники на них.5. Відсутній аналог delete.6. Методи класу можуть бути перевантажені,

розрізнення – за сигнатурою.7. Можна визначати операції, в т.ч. індексатори.8. Властивості.9. За замовченням параметри методів

передаються за значенням, це можна змінювати.

Page 3: Тема № 4

Особливості ООП у C# - продовження На вершині ієрархії – клас Object. Поліморфізм: за замовченням методи невіртуальні;

це можна змінювати. Вводяться інтерфейси як абстракція, що тільки

декларує поведінку, але не визначає її. Неявно типовані змінні. Generics. Ініціалізатори класів. Розвинені засоби RTTI та інтроспекції. Часткові класи. Анонімні класи та анонімні методи. Делегати. Події.

Page 4: Тема № 4

Особливості ООП у C#: продовження Розширюючі методи. Риси, характерні для функціонального

програмування (ламбда-вирази і т.п). LINQ.

Page 5: Тема № 4

Класи і об’єкти

Поняття класу та об’єкту в C# в цілому співпадає з загальноприйнятим.

Опис класу:

class KlName {

члени класу

}

Page 6: Тема № 4

Reference Type: загальна характеристика Загальна риса: доступ до змінних цих типів

здійснюється через вказівники на них. Але: змінні вказівникових типів ведуть себе подібно до

вказівників. Такими типами є, наприклад: екземпляри класів, в т.ч.

рядки; масиви. null - спеціальне значення для пустого вказівника.

Page 7: Тема № 4

Створення об’єктів. Конструктори За допомогою оператора new:KlName ekz=new KlName(параметри); І за синтаксисом, і за семантикою це виклик

конструктора - спеціального методу, який описує, які дії повинні виконуватися при ініціалізації об’єкта.

Синтаксично - метод, ім’я якого співпадає з іменем класу. Нічого не повертає (навіть void).

Конструктори можуть бути перевантажені. Якщо конструкторів немає - надається

конструктор за замовченням. Але, якщо є хоча б один конструктор -

конструктор за замовченням не надається.

Page 8: Тема № 4

Характерний приклад

Нехай є клас Kl і оголошення Kl ekz;Чи означає це оголошення створення екземпляру класу і

виділення пам’яті під нього?Ні, створюється лише вказівник відповідного типу.Сам екземпляр створюється шляхом виклику

конструктора класу:Kl ekz = new Kl(…);Аналогічно - операції.

Page 9: Тема № 4

Екземпляри класів

a vN1a

N1

vN2a

N2

b vN1b

N1

vN2b

N2b=a;

b.N1=vNEW;вив. a.N1; //vNEW

Page 10: Тема № 4

Рядки: особливість (рядки є незмінюваними)

a “AAAA”

b “BBBB”

b=a;b=“CCCC”;вив. а; //AAAA

“CCCC”

Page 11: Тема № 4

Модифікатори доступу

public – загальнодоступні; protected – доступні для підкласів; internal – доступні для класів в межах тієї ж

збірки; internal protected – доступні для підкласів, а

також для будь-яких класів у межах збірки; private - тільки для класу, в якому вони визначені

(для членів класу – за замовченням).

Page 12: Тема № 4

Запитання Чи може конструктор класу бути

приватним?

Page 13: Тема № 4

Використання приватних конструкторів: паттерн Singleton

Singleton

- Singleton instance =new Singleton()

- Singleton()

+ Singleton getInstance()

return instance;

Page 14: Тема № 4

Поняття властивості

Концепція властивостей є однією з найбільш характерних рис C#.

Властивість – це конструкція, яка передбачає методи get та/або set для отримання або встановлення відповідного значення.

Page 15: Тема № 4

Приклад властивості (“класичний” синтаксис)У класі:int QP;

public int Q { get { return QP; } set { QP = value; } }

У клієнті, який використовує клас:sp.Q = 2;

Page 16: Тема № 4

Властивості: коментар до прикладу Ззовні звернення до властивості

виглядає як звернення до поля. У найбільш типовому випадку властивість

пов’язана з окремим полем, але це не обов’язково. У цьому випадку може бути так, що деяка властивість L встановлюється в одне значення, а при зчитуванні отримуємо інше значення.

Якщо потрібно тільки для читання або для запису – тільки get або, відповідно, set.

Page 17: Тема № 4

Приклад

public int L

{

get { return QP + LP; }

set { LP = value; }

}

Page 18: Тема № 4

З 2.0 – можливість розділення прав доступу В С# 2.0 з’явилася можливість розділити

права доступу для селекторів (get) і модифікаторів (set).

Приклад:

public int L

{

get { return QP + LP; }

private set { LP = value; }

}

Page 19: Тема № 4

Новий спрощений синтаксис для властивостей – з C# 3.0

public int R { get; set; }

Page 20: Тема № 4

Новий синтаксис ініціалізації об’єктів – з C# 3.0

Kl s1 = new Kl { R = 30 };

Семантично це еквівалентно виклику конструктора класу без параметрів і встановленню значень полів або властивостей.

Page 21: Тема № 4

Cпадкування

class K1 : K2 {. . .}

К1-підклас; К2-суперклас.

Так само, як і Java, C# не підтримує множинного спадкування.

На вершині ієрархії – клас System.Object.

Page 22: Тема № 4

Закриті класи і методи

Модифікатор sealed. Для класів цей модифікатор означає, що

від цього класу не можна утворювати похідні класи. Таким є, наприклад, клас string.

Для методів цей модифікатор означає, що цей метод не можна перевизначати в підкласах.

Page 23: Тема № 4

Вказівники this та base

this - вказівник на даний екземпляр. Передається методам екземпляра (нестатичним

методам) як неявний параметр. Одне з типових використань - в конструкторах. base – посилання на суперклас (нестатичне).

Page 24: Тема № 4

Виклик іншого конструктора

Того ж класу:

public Kl(…):this(…) {

}

Суперкласу:

public Kl(…):base(…) {

}

Page 25: Тема № 4

Статичні поля і методи

Супроводжуються модифікатором static. Поля і методи класу, а не екземпляру. Для статичних полів - одна копія для всіх

екземплярів; для нестатичних - кожний екземпляр має свою копію. Одне з типових використань - підрахунок кількості екземплярів класу.

Виклик - через ім’я класу. З статичними полями і методами можна

працювати, коли ще немає жодного екземпляра.

Page 26: Тема № 4

Статичні поля і методи: продовження Статичні методи не можуть викликати

нестатичні методи, а також звертатися до нестатичних полів.

Типовий механізм ініціалізації статичних полів – статичний конструктор, тобто конструктор з модифікатором static.

Статичним може бути і весь клас – якщо в ньому є лише статичні члени. Неможливо створити екземпляр такого класу; звернення до методів можуть бути тільки статичними.

Page 27: Тема № 4

Приклад статичного класу (ілюструється також readonly)static class Stalker { static readonly public int Pole;

static Stalker() //статичний конструктор { Pole = 10; } static public void Metod() { Console.WriteLine(Pole); } }

Page 28: Тема № 4

Ланцюжки конструкторів

Перед виконанням конструктора підкласу автоматично викликається конструктор суперкласу.

Page 29: Тема № 4

Поліморфізм у C#: початок

Об’єктна змінна суперкласу може посилатися на екземпляр підкласу, або посиланню на суперклас може бути надано значення посилання на підклас (розширююче перетворення).

Розширююче перетворення здійснюється автоматично; знижуюче слід робити явно.

“Безпечне” приведення – as. Перевірка типу – is.

Page 30: Тема № 4

Поліморфізм: віртуальні функції

Класичний приклад: оголошуємо клас Base з методом Metod та його підклас Sub, в якому теж є метод Metod. Створюємо екземпляр класу Sub і викликаємо метод Metod. Метод якого саме класу буде викликаний?

Page 31: Тема № 4

Віртуальні функції: загальні орієнтири За замовченням методи C# не є

віртуальними, але їх можна зробити віртуальними за допомогою модифікатора virtual.

Статичні, а також приватні методи не можуть бути віртуальними.

Важливі модифікатори: override – заміщення; new – затінення.

Page 32: Тема № 4

Демонстрація: Polimorf

class Bas { public virtual void Metod() { Console.WriteLine("Base class"); } } class Der : Bas { public void Metod() // new чи override ? { Console.WriteLine("Derived class"); } }

Page 33: Тема № 4

Використання

Bas b = new Der(); //якщо var – може бути //інакше

b.Metod();

Page 34: Тема № 4

Quiz: що виведе програма

static void Main(string[] args) { D d = new D(); C c = d; B b = c; A a = b; d.M(); c.M(); b.M(); a.M(); Console.ReadLine(); } } class A { public virtual void M() { Console.Write("A"); } } class B:A { public override void M() { Console.Write("B");} } class C : B { new public virtual void M() { Console.Write(“С");} } class D : C { public override void M() {Console.Write("D"); } }

Page 35: Тема № 4

Абстрактні методи і класи

Абстрактний метод - метод без реалізації; він супроводжується модифікатором abstract.

Передбачається, що такі методи повинні перевизначатися в підкласах. Тому абстрактні методи автоматично є віртуальними.

Абстрактні методи не мають тіла:public abstract int fun(); Якщо клас містить хоча б один абстрактний

метод, він сам повинен бути оголошений як абстрактний.

Для абстрактного класу не можна створювати екземпляри.

Page 36: Тема № 4

Інтерфейси

Логічний розвиток ідеї абстрактних класів. Всі методи інтерфейсу є абстрактними і

неявно є public (хоча явно вказувати ці модифікатори не дозволяється).

Інтерфейси не можуть містити полів (на відміну від Java).

Але інтерфейси можуть містити властивості.

В C# прийнято починати назви інтерфейсів з літери I, закінчуються вони часто на able.

Page 37: Тема № 4

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

Можна сказати, що інтерфейс - це набір вимог, які висуваються до класу, що його реалізує.

Якщо клас реалізує інтерфейс, то він повинен визначити всі методи, які описані в інтерфейсі.

Синтаксис: class Kl : I {… Клас може реалізувати декілька інтерфейсів; у

цьому випадку вони перелічуються через кому. Якщо, крім цього, клас Kl спадкує від іншого класу

B та реалізує кілька інтерфейсів – class Kl: B,I1,I2,…

Між інтерфейсами може бути відношення спадкування, причому таке спадкування може бути множинним.

Page 38: Тема № 4

Приклад: інтерфейс

interface I { int Pole { get; set; } void Metod(); }

class Kl : I { public int Pole { get; set; } public void Metod() { Console.WriteLine("Interface implemented with field

"+Pole); }}

Page 39: Тема № 4

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

Закриття методу інтерфейсу в класі; тоді для звернення до такого методу треба використовувати вказівник інтерфейсу.

Випадок, коли реалізується кілька інтерфейсів, і відповідний метод для кожного інтерфейсу потрібно визначити по-своєму.

Page 40: Тема № 4

Приклад явної реалізації інтерфейсів. Інтерфейсиinterface I1 { void Metod(); }

interface I2 { void Metod(); }

Page 41: Тема № 4

Приклад явної реалізації інтерфейсів. Класclass Kl : I1,I2 { void I1.Metod() { Console.WriteLine("First Interface"); } void I2.Metod() { Console.WriteLine("Second Interface"); } }

Page 42: Тема № 4

Приклад явної реалізації інтерфейсів. Звернення

I1 ekz1 = new Kl();

I2 ekz2 = (I2) ekz1; //один об’єкт – різні типи!

ekz1.Metod();

ekz2.Metod();

Page 43: Тема № 4

Перевантаження операторів - прикладclass Kl { public int Pole; public Kl(int Pole) { this.Pole = Pole; } public static Kl operator +(Kl a, Kl b) { return new Kl(a.Pole + b.Pole); } }

Page 44: Тема № 4

В основній програмі

class Program

{

static void Main(string[] args)

{

Kl a = new Kl(10) + new Kl(15);

Console.WriteLine(a.Pole);

Console.ReadLine();

}

}

Page 45: Тема № 4

Перевантаження операторів – деякі особливості Всі оператори мають бути описані як public і

static. Не можна перевантажувати ряд операторів,

зокрема =. Якщо перевантажується +, то +=

перевантажується автоматично. Можуть перевантажуватися true та false (буде

робитися приклад на цю тему). Для операторів приведення типів може бути

заданий явний або неявний режим виклику (див. наступний слайд).

Page 46: Тема № 4

Модифікатори explicit та implicit

Використовуються у визначеннях операторів приведення типів для задання того, чи буде перетворення здійснюватися неявно, чи приведення типів слід робити явним чином.

Page 47: Тема № 4

Приклад приведення типів: клас; неявне перетворенняclass Person { public String Name { get; set; } public String Citizen { get; set; }

public static implicit operator String (Person p)

{return String.Format("Name: {0} ; Citizen: {1}",p.Name,p.Citizen);

} }

Page 48: Тема № 4

Використання неявного перетворення Person p1 = new Person { Name = "Bob

Robber", Citizen = "UK" };

String s = p1;

Console.WriteLine(s);

Page 49: Тема № 4

Клас: явне перетворення

class Person { public String Name { get; set; } public String Citizen { get; set; }

public static explicit operator String (Person p)

{return String.Format("Name: {0} ; Citizen: {1}",p.Name,p.Citizen);

} }

Page 50: Тема № 4

Явне перетворення: використанняPerson p1 = new Person { Name = "Bob

Robber", Citizen = "UK" };

String s = (String)p1;

Console.WriteLine(s);

Page 51: Тема № 4

Індексатори

Відповідають параметризованим властивостям специфікації CLR.

В C# - щось подібне до встановлення операції звернення за індексом.

Приклад – клас, який реалізує “безпечний” масив, тобто при зверненні до елементу масиву в межах допустимого діапазону повертається відповідне значення, в іншому випадку – 0. При цьому бажано, щоб звернення відбувалося так, як звичайне звернення до масиву, а нумерація починалася з 1.

Page 52: Тема № 4

Код класу з індексатором

class Kl { public int[] M = new int[10]; // базовий масив public int this[int index] { get { if ((index <= 10) && (index > 0)) return M[index - 1]; else return 0; } set { if ((index<=10)&&(index>0)) M[index-1] = value; } } }

Page 53: Тема № 4

Індексатори: інші типові використання “Неявний” масив, тобто звернення як до

масиву, але значення обчислюється динамічно.

Якщо потрібно в класі реалізувати щось на зразок асоціативного масиву.

Page 54: Тема № 4

Структури

Структури – типи даних, які багато в чому подібні до класів (з певними обмеженнями), але структури – це ValueType!

Page 55: Тема № 4

Приклад структури

struct Person { public string Name; public int Age;

public Person(String Name, int Age) { this.Name = Name; this.Age = Age; }

public override string ToString() { return Name + " - " + Age; } }

Page 56: Тема № 4

Використання структур

// Різні способи ініціалізації Person t1; // new не обов’язкове t1.Age = 10; t1.Name = "Ivanov";

Person t2 = new Person(); // але можливе t2.Name = "Petrov"; t2.Age = 105;

Person t3 = new Person { Name = "Sidorov", Age = 37 }; Person t4 = t1; //копіювання, характерне для Value Type t4.Age = 99;

Person t5 = new Person("Hun Vei Bin", 18);

Page 57: Тема № 4

Структури: деякі обмеження

Структури не підтримують спадкування, але можуть реалізовувати інтерфейси.

Можуть бути конструктори, але не можна задати конструктор за замовченням.

В структурах не можна ініціалізувати поля за замовченням.

Page 58: Тема № 4

Навіщо потрібні структури

Питання ефективності: доступ здійснюється напряму, а не через вказівники.

Page 59: Тема № 4

Деструктори

В C# немає аналога delete. Збирання “сміття” (об’єктів, на які не

залишилося доступних посилань), здійснюється збирачем сміття автоматично.

Можна описати деструктор, який буде викликаний збирачем сміття перед знищенням об’єкта. Деструктор автоматично компілюється в метод Finalize, який гарантовано викликає аналогічний метод для батьківського класу.

Форсоване збирання сміття – GC.Collect().

Page 60: Тема № 4

Приклад класу з деструктором

class Kl { static int i = 1; public int Number = 0; public Kl() { this.Number = i++; Console.WriteLine("Створено об'єкт з номером {0}",

this.Number); ~Kl() { Console.WriteLine("Знищено об'єкт з номером {0}",

this.Number); } }

Page 61: Тема № 4

Покоління

Для збирача сміття важливим є термін “покоління”.

Нульове, перше, друге. Об’єкти, які залишилися після збирання

сміття, переходять до наступного покоління.

Збір сміття починається з нульового покоління.

Page 62: Тема № 4

Альтернатива деструкторам

Інтерфейс IDisposable та метод Dispose. Більш явне керування процесом

звільнення непотрібних ресурсів. Рекомендується комбінувати з

деструкторами.

Page 63: Тема № 4

Приклад Disposable-класу

class MyClass : IDisposable

{

public void Dispose()

{

Console.WriteLine("The end of honorless existence");

}

}

Page 64: Тема № 4

Можливе використання

try { MyClass inst = new MyClass();… } finally { if (inst != null) { inst.Dispose(); } } }

Page 65: Тема № 4

Або використання using:

using (MyClass inst = new MyClass())

{

}