Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

125 Кібербезпека / Магістр (вступні питання)

.pdf
Скачиваний:
108
Добавлен:
23.10.2019
Размер:
3.84 Mб
Скачать

В РНР5 вперше вводяться поняття «абстрактного класу» та методу. Абстракті методи мають тільки об‘яву і не мають реалізації. Клас, який має

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

<?php

abstract class MyClass {

abstract public function abstrFunc();

}

class MyClass1 extends MyClass { public function abstrFunc() {

echo 1;

}

}

$obj = new MyClass1; $obj->abstrFunc(); // Виводится 1

?>

При цьому неможливо створити об'єкт абстрактного класу, можна тільки визначати нові класи від базового абстрактного класу і створювати об'єкти вже від похідних класів.

Варто відзначити, що абстрактні класи також можуть містити і звичайні (не абстрактні) елементи.

Інтерфейс

Інтерфейсами є абстрактні класи, що містять тільки абстрактні методи і не мають ніяких властивостей.

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

При цьому в інтерфейсі методи оголошуються ключовим словом function без зазначення будь-яких специфікаторів, в тому числі й abstract.

<?php

interface Int1 { function func1();

}

interface Int2 { function func2();

}

class MyClass implements Int1, Int2 { public function func1() {

echo 1;

}

public function func2() { echo 2;

}

}

$obj = new MyClass; $obj->func1(); // Виводить 1 $obj->func2(); // Виводить 2

?>

Таким чином, хоча множинне спадкування і не підтримується в PHP 5, проте розробники отримали реальну можливість створювати класи на основі окремо описаних інтерфейсів.

Визначення об'єкта класу

Часто трапляється, що необхідно визначити, чи є даний об'єкт екземпляром певного класу, або ж він реалізує певний інтерфейс. Це може бути зроблено за допомогою оператору instanceof:

if ($obj instanceof MyClass) {

echo "\$obj is an instance of MyClass";

}

Оператор instance of також дозволяє перевіряти всі класи-нащадки вашого об‘єкту , а також будь-які інтерфейси.

67. Перевантаження методів класів в ООП. Перевантаження операторів

Перевантаження функції, перевантаження процедури або

ж перевантаження методу (англ. function overloading or method overloading) —

в програмуванні один із засобів реалізації поліморфізму (ad hoc поліморфізм), що полягає в можливості створювати кілька реалізацій функції (методу) із тим же ім'ям проте з різною сигнатурою — з різною кількістю параметрів або з різним типом параметрів[1]. Дана можливість з'явилась ще в процедурних мовах програмування, з появою ж об'єктно-орієнтованого підходу можливість поширилась на методи (функції-члени) одного і того ж класу, зокрема і на конструктори класу.

Для прикладу, doTask() та doTask(object O) — це два різні

перевантажені методи. Перший метод не має параметрів, а другий має ту ж назву, проте може приймати як параметр певний об'єкт

Перевантаження методів

● Так само як і для звичайних методів, у методах класу припустима директива overload - метод, що перевантажується:

TOver1Class=class(TObject)

public

procedure DoSmth(N:i Микола Скрипський. Програмування. ceo@mgm.cv.ua 22 Перевантаження методів

Наступні методи, що перевантажуються, можуть бути оголошені як у вихідному класі, так і в класах-нащадках:

TOver2Class=class(TOver1Class)

public

procedure DoSmth(S:string); overload;

class procedure DoSecond(S:string); reintroduce; overload; dynamic;

end;

Перевантаження методів

Тепер можна викликати методи DoSmth і DoSecond з екземпляра TOver2Class із цілочисельним і рядковим параметром:

procedure TForm1.Button3Click(Sender: TObject);

var

CO:TOver2Class;

begin

CO:=TOver2Class.Create;

CO.DoSmth(1);

CO.DoSmth('Test');

CO.Free;

end;

Перевантаження операторів — в програмуванні один із засобів реалізації поліморфізму (спеціалізований поліморфізм), що полягає в можливості одночасного існування в одній зоні видимості декількох різних

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

В кожній предметній області існують свої стандартні позначення, що полегшують наведення і обговорення концепцій, що часто зустрічаються. Наприклад, завдяки постійному використанню вираз

x+y*z

є зрозумілішим, ніж фраза

помножити y на z і додати результат до x

або навіть

add (x, multiply (y,z))

Перевантаження операторів — це синтаксичний цукор для короткої і виразної форми запису типових операцій.

Приклад

#include <stdio.h> // для printf

class X

{

int x; public:

X() : x(0) {}

explicit X(int i) : x(i) {} operator int() { return x; }

X& operator=(const X& arg1) { x = arg1.x; return *this; } friend const X operator+(const X&, const X&);

friend const X operator*(const X&, const X&);

};

//використання дружніх функцій дозволяє доступ до приватних членів класу

//і також дозволяє показати симетричність в оголошенні функції.

//застосування модифікатора const к значенню до повернення перешкоджає

//написанню дивних виразів подібних до такого X(5) + X(6) = X(7)

inline const X operator+(const X& arg1, const X& arg2)

{

X r;

r.x = arg1.x + arg2.x; return r;

}

inline const X operator*(const X& arg1, const X& arg2)

{

X r;

r.x = arg1.x * arg2.x; return r;

}

int main()

{

X x;

x = X(5) + X(6) * X(7); // = 47 ( * має вищий пріоритет )

//x = 5 + 6 * 7; - не спрацює через використання explicit,

//а x = X(5 + 6 * 7); можна

printf("%d\n", x); // завдяки operator int() х неявно перетворюється в int

}

68. Колекції в мовах програмування. Колекції для роботи зі списками та множинами

Колекція в програмуванні - програмний об'єкт, що містить у собі, тим чи іншим чином, набір значень одного або різних типів, і дозволяє звертатися до цих значень.

Колекція дозволяє записувати в себе значення і витягати їх. Призначення колекції - служити сховищем об'єктів і забезпечувати доступ до них. Зазвичай колекції використовуються для зберігання груп однотипних об'єктів, що підлягають стереотипної обробці. Для звернення до конкретного елементу колекції можуть використовуватися різні методи, в залежності від її логічної організації. Реалізація може допускати виконання окремих операцій над колекціями в цілому. Наявність операцій над колекціями у багатьох випадках може істотно спростити програмування.

1. Колекції та контейнери

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

2. Класифікація

2.1. За загальним характеристикам

Колекція може мати постійний або динамічно змінюваний розмір. У першому випадку в колекцію може бути записано тільки строго певну кількість об'єктів, у другому - колекція допускає розміщення стількох об'єктів, скільки необхідно (зрозуміло, в межах, що задаються технічними обмеженнями). У більшості випадків, говорячи про колекції, мають на увазі динамічну колекцію, тобто колекцію другого виду, хоча, наприклад, звичайний статичний масив - це теж колекція.

Колекція може зберігати об'єкти тільки одного або різних типів. У другому випадку говорять про гетерогенної колекції.

На рівні реалізації колекція може являти собою одну з наступних структур даних:

Масив

Односвязного список

Двусвязний список

Стек

Хеш-таблиця

Бітовий масив

3.Операції над колекціями

В залежності від логічного типу колекції і від реалізації можуть підтримуватися різні операції над колекціями в цілому. У всіх випадках операції можуть проводитися тільки над парами колекцій одного типу (і, якщо колекції не гетерогенні, з одним типом елементів). Можуть підтримуватися також наступні операції:

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

Для векторів і матриць, що містять числові значення - типові математичні операції над однойменними об'єктами: додавання, віднімання, множення, транспонування.

Для векторів - вилучення діапазону індексів. Результатом такої операції буде вектор того ж типу, що містить тільки ті елементи вихідного, які потрапляють в деякий заданий діапазон.

Для векторів і списків - сортування.

Для множин - об'єднання, перетин, різниця і симетрична різниця.

4.Відомі реалізації

Glib - бібліотека, що реалізує більшість колекцій під ліцензією GNU LGPL

STL - реалізація у вигляді бібліотеки шаблонів для C + +.

Робота зі списками

Інтерфейс List описує упорядковану колекцію (послідовність). Цей інтерфейс

реалізують

стандартні

класи ArrayList і LinkedList.

Клас ArrayList реалізує

список за

допомогою масиву змінної довжини.

Клас LinkedList зберігає

об'єкти

за допомогою так званого зв'язаного

списку.

 

 

 

У списках зберігаються посилання на java.lang.Object. Як і в масивах, доступ до елементів може здійснюватися за індексом (але не через операцію []). На відміну від масивів, розмір списків може динамічно змінюватися. Java надає варіанти створення списків як із застосуванням узагальнень, так і без них. Варіант без узагальнень вважається застарілим і небажаним.

Створити порожній список посилань на об'єкти деякого типу (SomeType) можна за допомогою конструктора за умовчанням:

List<SomeType> al = new ArrayList<SomeType>();

Можна також одразу описати посилання на ArrayList:

ArrayList<SomeType> al = new ArrayList<SomeType>();

Другий варіант іноді не є бажаним, оскільки в такому випадку знижується гнучкість програми. Перший варіант дозволить легко замінити реалізацію списку ArrayList на будь-яку іншу реалізацію інтерфейсу List, яка більше відповідає вимогам конкретної задачі. У другому випадку є спокуса викликати методи, специфічні для ArrayList, тому перехід на іншу реалізацію буде ускладнено.

Створивши порожній список, у нього можна додавати елементи за допомогою функції add(). Метод add() з одним аргументом типу Object (або похідних типів) додає елемент у кінець списку. Якщо ця функція викликається з двома аргументами, новий елемент вставляється в список у позиції, зазначеній першим параметром:

List<String> al = new ArrayList<String>(); al.add("abc");

al.add("def");

al.add("xyz");

al.add(2, "ghi"); // Вставка нового рядка перед "xyz"

До списку можна додати всі елементи іншого списку (або іншої колекції) за допомогою функції addAll().

Можна створити новий список із використанням існуючого. Новий список містить посилання на копії елементів. наприклад:

List<String> a1 = new ArrayList<String>(al);

За

допомогою

статичної

функції asList() класу java.util.Arrays можна

створити список з

існуючого масиву. Масив можна також створити безпосередньо у списку параметрів функції. Наприклад:

String[] arr = {"one", "two", "three"};

List<String> a2 = Arrays.asList(arr);

List<String> a3 = Arrays.asList("four", "five");

Для списків перевантажена функція toString(), яка дозволяє, наприклад, вивести всі елементи масиву на екран без використання циклів. Елементи виводяться у квадратних дужках:

System.out.println(a3); // [four, five]

Списки дозволяють роботу з окремими елементами. Метод size() повертає кількість елементів, що містяться в списку. Метод get() класу ArrayList повертає елемент із зазначеним індексом (позиція в списку). Як і елементи масивів, елементи списків пронумеровані з нуля. У наступному прикладі рядки виводяться за допомогою функції println():

List<String> al = new ArrayList<String>(); al.add("abc");

al.add("def");

al.add("xyz");

for (int i = 0; i < al.size(); i++) { System.out.println(al.get(i));

}

Функція subList(fromIndex, toIndex) повертає список, складений з елементів починаючи з елемента з індексом fromIndex і не включаючи елемент з індексом toIndex. Наприклад:

System.out.println(al.subList(1, 3)); // [def, xyz]

Метод set() дозволяє змінити об'єкт, що зберігається в зазначеній позиції. Метод remove() видаляє об'єкт у зазначеній позиції:

al.set(0, "new"); al.remove(2);

System.out.println(al); // [new, def]

Усі елементи колекцій віддаляються за

допомогою методу clear().

Функція contains() повертає true, якщо

список містить зазначений

елемент. Наприклад:

 

if (al.contains("abc"))

 

System.out.println(al);

 

Функція toArray() повертає посилання на масив копій об'єктів, посилання на які зберігаються в списку.

Object [] a = al.toArray(); System.out.println(a[1]); // def

(al.toArray()) [2] = "text"; // Зміна елементів нового масиву

// []

Для збереження цілих і дійсних значень у колекціях часто використовують класи-оболонки Integer та Double відповідно.

У тих випадках, коли частіше, ніж вибір довільного елемента, застосовують операції додавання і видалення елементів у довільних місцях, доцільно використовувати клас LinkedList, що зберігає об'єкти за допомогою зв'язаного списку. Для зручної роботи додані також методи addFirst(), addLast(), removeFirst() і removeLast().

LinkedList<String> list = new LinkedList<String>(); list.addLast("last"); // Те саме, що list.add("last"); list.addFirst("first");

System.out.println(list); // [first, last] list.removeFirst();

list.removeLast(); System.out.println(list); // []

Ці специфічні функції додані саме в LinkedList, оскільки вони не можуть бути ефективно реалізовані в ArrayList із застосуванням масивів.

Зв'язний список, реалізований у Java контейнером LinkedList, є двоспрямований список, де кожен елемент містить посилання на попередній і наступний елементи.

Робота з множинами

Множина - це колекція, що не містить однакових елементів. Три основних

реалізації інтерфейсу Set - HashSet, LinkedHashSet і TreeSet.

Як і

списки,

множини

є

узагальненими

типами.

Класи HashSet і LinkedHashSetвикористовують

хеш-коди

для

ідентифікації

елемента. Клас TreeSet використовує

двійкове дерево для

збереження елементів і гарантує їх певний порядок.

 

 

Метод add() додає елемент до множини і повертає true якщо елемент раніше був відсутній. В іншому випадку елемент не додається, а метод add() повертає false. Усі елементи множини видаляються за допомогою методу clear().

Set<String> s = new HashSet<String>(); System.out.println(s.add("First")); // true System.out.println(s.add("Second")); // true System.out.println(s.add("First")); // false System.out.println(s); // [First, Second] s.clear();

System.out.println(s);

Метод remove() видаляє зазначений елемент множини, якщо

такий є.

Метод contains() повертає true, якщо множина містить

зазначений

елемент.

 

У наведеному нижче прикладі до множини цілих чисел додається десять випадкових значень у діапазоні від -9 до 9:

package ua.in.iwanoff.labs.third; import java.util.*;

public class SetOfIntegers {

public static void main(String[] args) { Set<Integer> set = new TreeSet<Integer>(); Random random = new Random();

for (int i = 0; i < 10; i++) {

Integer k = random.nextInt() % 10; set.add(k);

}

System.out.println(set);

}

}

Результуюча множина як правило містить менш, ніж 10 чисел, оскільки окремі значення можуть повторюватися. Оскільки ми використовуємо TreeSet, числа зберігаються та виводяться в упорядкованому (за зростанням) вигляді. Для того, щоб додати саме десять різних чисел, програму можна модифікувати, наппиклад із застосуванням циклу while замість for:

while (set.size() < 10) {

. . .

}

Можна створити масив, який містить копії елементів множини. В такий спосіб можна звертатися до елементів за індексом. Наприклад, так можна вивести елементи множини в зворотному порядку:

for (int i = set.size() - 1; i >= 0; i--) { System.out.println(set.toArray()[i]);

}

Оскільки множина може містити тільки різні елементи, її можна використати для підрахунку різних слів, літер, цифр тощо - створюється множина та викликається метод size(). Застосовуючи TreeSet, можна виводити слова та літери в алфавітному порядку. У наступному прикладі вводиться речення та