Інформація про навчальний заклад

ВУЗ:
Національний університет Львівська політехніка
Інститут:
О
Факультет:
КН
Кафедра:
Не вказано

Інформація про роботу

Рік:
2018
Тип роботи:
Звіт до лабораторної роботи
Предмет:
Кросплатформенні засоби програмування

Частина тексту файла (без зображень, графіків і формул):

Міністерство освіти і науки України Національний університет “Львівська політехніка” / Звіт До Лабораторної роботи №4 З дисципліни: «Кросплатформені засоби програмування» Мета: ознайомитися з спадкуванням та інтерфейсами у мові Java. ТЕОРЕТИЧНІ ВІДОМОСТІ Спадкування Спадкування в ООП призначене для розширення функціональності існуючих класів шляхом утворення нових класів на базі вже існуючих. У Java реалізована однокоренева архітектура класів згідно якої всі класи мають єдиного спільного предка (кореневий клас в ієрархії класів) – клас Object. Решта класів мови Java утворюються шляхом успадковування даного класу. Будь-яке спадкування у мові Java є відкритим, при цьому аналогів захищеному і приватному спадкуванню мови С++ не існує. На відміну від С++ у Java можливе спадкування лише одного базового класу (множинне спадкування відсутнє). Спадкування реалізується шляхом вказування ключового слова class піcля якого вказується назва підкласу, ключове слово extends та назва суперкласу, що розширюється у новому підкласі. Синтаксис реалізації спадкування: class Підклас extends Суперклас { Додаткові поля і методи } В термінах мови Java базовий клас найчастіше називається суперкласом, а похідний клас – підкласом. Дана термінологія запозичена з теорії множин, де підмножина міститься у супермножині. При наслідувані у Java дозволяється перевизначення (перевантаження) методів та полів. При цьому область видимості методу, що перевизначається, має бути не меншою, ніж область видимості цього методу у суперкласі, інакше компілятор видасть повідомлення, про обмеження привілеїв доступу до даних. Перевизначення методу полягає у визначені у підкласі методу з сигнатурою методу суперкласу. При виклику такого методу з-під об’єкта підкласу викличеться метод цього підкласу. Якщо ж у підкласі немає визначеного методу, що викликається, то викличеться метод суперкласу. Якщо ж у суперкласі даний метод також відсутній, то згенерується повідомлення про помилку. Перевизначення у підкласах елементів суперкласів (полів або методів) призводить до їх приховування новими елементами. Бувають ситуації, коли у методах підкласу необхідно звернутися до цих прихованих елементів суперкласів. У цій ситуації слід використати ключове слово super, яке вказує, що елемент до якого йде звернення, розташовується у суперкласі, а не у підкласі. Синтаксис звертання до елементів суперкласу: super.назваМетоду([параметри]); // виклик методу суперкласу super.назваПоля // звертання до поля суперкласу Використання ключового слова super у конструкторах підкласів має дещо інший сенс, ніж у методах. Тут воно застосовується для виклику конструктора суперкласу. Виклик конструктора суперкласу має бути першим оператором конструктора підкласу. Конкретний конструктор, який необхідно викликати, вибирається по переданим параметрам. Явний виклик конструктора суперкласу часто є необхідним, оскільки підкласи не мають доступу до приватних полів суперкласів. Тож ініціалізація їх полів значеннями відмінними від значень за замовчуванням без явного виклику відповідного конструктора суперкласу є неможливою. Якщо виклик конструктора суперкласу не вказаний явно у підкласі або суперклас не має конструкторів, тоді автоматично викликається конструктор за замовчуванням суперкласу. Синтаксис виклику конструктора суперкласу з конструктора підкласу: public НазваПідкласу([параметри]) { super([параметри]); оператори конструктора підкласу } Поліморфізм Механізм поліморфізму забезпечує можливість присвоєння об’єктним змінним суперкласу об’єктів похідних класів та звертання з-під цих змінних до перевизначених у підкласі членів суперкласу. У Java всі об’єктні змінні є поліморфними. Поліморфізм реалізується за допомогою механізму динамічного (пізнього) зв’язування, який полягає у тому, що вибір методу, який необхідно викликати, відбувається не на етапі компіляції, а під час виконання програми. Для глибшого розуміння поліморфізму розглянемо покроково виклик методу класу: Компілятор визначає об’явлений тип об’єкту і ім’я методу та нумерує всі методи з однаковою назвою у класі та всі загальнодоступні методи з такою ж назвою у його суперкласах. Компілятор визначає типи параметрів, що вказані при виклику методу. Якщо серед усіх методів з вказаним іменем є лише один метод, типи параметрів якого співпадають з вказаним, то відбувається його виклик. Цей процес називається дозволом перевантаження. Якщо компілятор не знаходить жодного методу з підходящим набором параметрів або в результаті перетворення типів виявлено кілька методів, що відповідають даному виклику, то видається повідомлення про помилку. Якщо метод є приватним, статичним, фінальним або конструктором, то для нього застосовується механізм статичного зв’язування. Механізм статичного зв’язування передбачає визначення методу, який необхідно викликати, на етапі компіляції. В протилежному випадку метод, що необхідно викликати, визначається по фактичному типу неявного параметру (динамічне зв’язування). Якщо для виклику методу використовується динамічне зв’язування, то віртуальна машина повинна викликати версію методу, що відповідає фактичному типу об’єкту на який посилається об’єктна змінна. Оскільки на пошук необхідного методу потрібно багато часу, то віртуальна машина заздалегідь створює для кожного класу таблицю методів, в якій перелічуються сигнатури всіх методів і фактичні методи, що підлягають виклику. При виклику методу віртуальна машина просто переглядає таблицю методів. Якщо відбувається виклик методу з суперкласу за допомогою ключового слова super, то при виклику методу переглядається таблиця методів суперкласу неявного параметру. Приведення об’єктних типів Приведення типів у Java відбувається вказуванням у круглих дужках перед змінною, яку необхідно привести до іншого типу, типу до якого її необхідно привести. Синтаксис приведення змінної до іншого типу: (новийТип) змінна У Java усі об’єктні змінні є типізовані. Механізми наслідування і поліморфізму дозволяють створювати нові типи (класи та інтерфейси) на базі вже існуючих та присвоювати об’єкти цих типів посиланням на об’єкти супертипу. В цьому випадку об’єкти підтипів мають ті самі елементи, що й об’єкти супертипу, тож таке висхідне приведення типів є безпечним і здійснюється компілятором автоматично. Проте присвоєння посиланню на об’єкт підтипу об’єкту супертипу не завжди є коректним, тому таке приведення вимагає явного приведення типів. При такому приведенні типів можливі дві ситуації: якщо посилання на об’єкт супертипу реально посилається на об’єкт підтипу, то приведення посилання на об’єкт супертипу до типу підтипу є коректним; якщо посилання на об’єкт супертипу посилається на об’єкт супертипу, то приведення посилання на об’єкт супертипу до типу підтипу викличе виключну ситуацію ClassCastExeption. Наявність бодай одної такої виключної ситуації призводить до аварійного завершення програми. Щоб уникнути цього слід перед приведенням типів використати оператор instanceof, який повертає true, якщо посилання посилається на об’єкт фактичний тип якого є не вищим в ієрархії типів, ніж вказаний у операторі instanceof, і false у протилежному випадку. Синтаксис оператора instanceof: посилання instanceof Ім’яТипу Таким чином, основні правила приведення типів є наступними: Приведення типів можна виконувати лише в ієрархії спадкування. Щоби перевірити коректність приведення супертипу до підтипу слід використовувати оператор instanceof. Абстрактні класи Абстрактні класи призначені бути основою для розробки ієрархій класів та не дозволяють створювати об’єкти свого класу. Вони реалізуються за допомогою ключового слова abstract. На відміну від звичайних класів абстрактні класи можуть містити абстрактні методи (а можуть і не містити). Абстрактні методи – це методи, що оголошені з використанням ключового слова abstract і не місять тіла. Розширюючи абстрактний клас можна залишити деякі або всі методи невизначеними. При цьому підклас автоматично стане абстрактним. Перевизначення у підкласі усіх абстрактних методів призведе до того, що підклас не буде абстрактним, що дозволить створювати на його основі об’єкти класу. Синтаксис оголошення абстрактного класу наведено в пункті «Класи та об’єкти». Синтаксис оголошення абстрактного методу: [СпецифікаторДоступу] abstract Тип назваМетоду([параметри]); Абстрактні класи корисні тоді, коли в ієрархії класів необхідно реалізувати методи з однаковими назвами, проте різною функціональністю і можливістю поліморфного виклику методів підкласів з-під посилання на абстрактний суперклас. Також використовуються при створенні інтерфейсів. Інтерфейси Інтерфейси вказують що повинен робити клас не вказуючи як саме він це повинен робити. Інтерфейси покликані компенсувати відсутність множинного спадкування у мові Java та гарантують визначення у класах оголошених у собі прототипів методів. Синтаксис оголошення інтерфейсів: [public] interface НазваІнтерфейсу { Прототипи методів та оголошення констант інтерфейсу } Інтерфейси можуть містити прототипи методів, які мають визначатися у класі, що відповідає цьому інтерфейсу, і константи, які автоматично успадковуються класом, що реалізує цей інтерфейс. Всі методи інтерфейсу вважаються загальнодоступними, тому оголошувати методи як public у інтерфейсі нема необхідності. Всі поля, що оголошені у інтерфейсі автоматично вважаються такими, що оголошені як public static final, тому додавати ці модифікатори самостійно необхідності також нема. Інтерфейси можуть успадковувати інші інтерфейси, утворюючи таким чином ієрархії інтерфейсів. Синтаксис реалізації спадкування у інтерфейсів співпадає з синтаксисом реалізації спадкування у класах. Оскільки інтерфейс не є класом, то створити його об’єкт за допомогою оператора new неможливо. Проте можна оголосити посилання на інтерфейсний тип та присвоїти цьому посиланню об’єкт, що реалізує цей інтерфейс. На відміну від спадкування клас може реалізувати кілька інтерфейсів. Ця особливість і компенсує відсутність множинного спадкування у мові Java. Щоб клас реалізував інтерфейс необхідно: Оголосити за допомогою ключового слова implements, що клас реалізує інтерфейс. Якщо клас реалізує кілька інтерфейсів, то вони перелічуються через кому після ключового слова implements. Визначити у класі усі методи, що вказані у інтерфейсі. Виконання лабораторної роботи Завдання: Варіант 14 Телевізор з тюнером Написати та налагодити програму на мові Java, що розширює клас, що реалізований у лабораторній роботі №3, для реалізації предметної області заданої варіантом. Суперклас, що реалізований у лабораторній роботі №3, зробити абстрактним. Розроблений підклас має забезпечувати механізми свого коректного функціонування та реалізовувати мінімум один інтерфейс. Код програми: package ki43.karabas.Lab4; public interface Tuner { void addChannelsFromSatellite(); } package ki43.karabas.Lab4; import javafx.util.Pair; import java.nio.file.Files; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.util.*; class Screen { private int width; private int height; public Screen() { width = 100; height = 100; } public Screen(int width, int height) { if (width < 0 || height < 0) { throw new IllegalArgumentException("Screen width and height must be positive number"); } this.width = width; this.height = height; } public Screen(Screen other) { this.width = other.width; this.height = other.height; } public int getWidth() { return width; } public void setWidth(int width) { if (width < 0) { throw new IllegalArgumentException("Screen width and height must be positive number"); } this.width = width; } public int getHeight() { return height; } public void setHeight(int height) { if (height < 0) { throw new IllegalArgumentException("Screen width and height must be positive number"); } this.height = height; } public void setResolution(int width, int height) { setHeight(height); setWidth(width); } } class Channels { private List<String> channels = new ArrayList<>(); public Channels() { } public Channels(Collection<String> channels) { this.channels.addAll(channels); } public Channels(Channels channels) { this.channels.addAll(channels.channels); } public List<String> getChannels() { return channels; } public void addChanel(String chanel) { if (channels.contains(chanel)) { throw new IllegalArgumentException("This channel already at list"); } channels.add(chanel); } public void removeChanel(String chanel) { if (channels.contains(chanel)) { throw new IllegalArgumentException("No such channel at list"); } channels.remove(chanel); } public boolean hasChanel(String chanel) { return channels.contains(chanel); } public String getNext(String chanel) { if (!channels.contains(chanel)) { return null; } int i = channels.indexOf(chanel); if (i == channels.size()) { return null; } return channels.get(i + 1); } public String getPrev(String chanel) { if (!channels.contains(chanel)) { return null; } int i = channels.indexOf(chanel); if (i == 0) { return null; } return channels.get(i - 1); } } public class TV { private Screen screen; private Channels channels; private String currentChanel; private boolean isWorking; private static final String LOG_FILE = "log.txt"; public TV() { this.screen = new Screen(); this.isWorking = false; this.channels = new Channels(); } public TV(int width, int height, Collection<String> channels) { this.screen = new Screen(width, height); this.channels = new Channels(channels); this.isWorking = false; } public TV(int width, int height) { this(width, height, Collections.emptyList()); } public TV(TV tv) { this.channels = new Channels(tv.channels); this.screen = new Screen(tv.screen); this.currentChanel = tv.currentChanel; this.isWorking = tv.isWorking; } public void turnOn() { log("Turn on TV"); isWorking = true; } public void turnOff() { log("Turn off TV"); isWorking = false; } public boolean isWorking() { log("Is TV working: " + isWorking); return isWorking; } protected static void log(String text) { try { Files.write(Paths.get(LOG_FILE), (text + "\n").getBytes(), StandardOpenOption.APPEND); } catch (Exception e) { e.printStackTrace(); } } public void addChanel(String... channels) { log("Add channels: " + String.join(", ", channels)); Arrays.stream(channels).forEach(this.channels::addChanel); } public Collection<String> getChannels() { log("Current list of channels: " + String.join(", ", channels.getChannels())); return new ArrayList<>(channels.getChannels()); } public void setCurrentChanel(String currentChanel) { if (!isWorking) { System.err.println("You must turn on TV first"); } else if (!channels.hasChanel(currentChanel)) { System.err.println("No such chanel"); } else { log("Set channel to " + currentChanel); this.currentChanel = currentChanel; } } public String getCurrentChanel() { log("Get current channel"); if (!isWorking) { System.err.println("You must turn on TV first"); return null; } else { log("Current channel is " + currentChanel); return currentChanel; } } public void goToNextChanel() { if (!isWorking) { System.out.println("You must turn on TV first"); } else { log("Go to next channel"); Optional<String> next = Optional.ofNullable(channels.getNext(currentChanel)); next.ifPresentOrElse(this::setCurrentChanel, () -> System.err.println("Can't go to next chanel")); } } public void goToPreviousChanel() { if (!isWorking) { System.out.println("You must turn on TV first"); } else { log("Go to previous channel"); Optional<String> next = Optional.ofNullable(channels.getPrev(currentChanel)); next.ifPresentOrElse(this::setCurrentChanel, () -> System.err.println("Can't go to next chanel")); } } public void setScreen(Screen screen) { log("Set screen resolution"); setScreenResolution(screen.getWidth(), screen.getHeight()); } public Screen getScreenResolution() { log("Get screen resolution"); return screen; } public void setScreenResolution(Pair<Integer, Integer> resolution) { log("Set screen resolution"); setScreenResolution(resolution.getKey(), resolution.getValue()); } public void setScreenResolution(int width, int height) { log("Set screen resolution"); if (width < 0 || height < 0) { System.out.println("Width and height must be bigger than 0"); } else { screen.setResolution(width, height); } } } package ki43.karabas.Lab4; import javafx.util.Pair; public class TVApp { public static void main(String[] args) { var t1 = new TVWithTuner(); t1.getCurrentChanel(); t1.turnOn(); t1.addChanel("1+1", "5", "ICTV"); t1.setCurrentChanel("5"); t1.setScreenResolution(1200, 800); t1.getCurrentChanel(); t1.addChannelsFromSatellite(); var t2 = new TV(t1); t2.goToNextChanel(); t2.goToPreviousChanel(); t2.setCurrentChanel("1+1"); var t3 = new TV(200, 400); t3.setScreenResolution(new Pair<>(200, 400)); t3.getScreenResolution(); t3.turnOff(); t3.isWorking(); } } package ki43.karabas.Lab4; public class TVWithTuner extends TV implements Tuner { @Override public void addChannelsFromSatellite() { log("Add channels from satellite"); addChanel("Jetix", "CartoonNetwork", "Mega"); } } Результат виконання програми: Get current channel Turn on TV Add channels: 1+1, 5, ICTV Set channel to 5 Set screen resolution Get current channel Current channel is 5 Add channels from satellite Add channels: Jetix, CartoonNetwork, Mega Go to next channel Set channel to ICTV Go to previous channel Set channel to 5 Set channel to 1+1 Set screen resolution Set screen resolution Get screen resolution Turn off TV Is TV working: false Висновок: на даній лабораторній роботі я ознайомився з спадкуванням та інтерфейсами у мові Java.
Антиботан аватар за замовчуванням

24.11.2018 18:11-

Коментарі

Ви не можете залишити коментар. Для цього, будь ласка, увійдіть або зареєструйтесь.

Ділись своїми роботами та отримуй миттєві бонуси!

Маєш корисні навчальні матеріали, які припадають пилом на твоєму комп'ютері? Розрахункові, лабораторні, практичні чи контрольні роботи — завантажуй їх прямо зараз і одразу отримуй бали на свій рахунок! Заархівуй всі файли в один .zip (до 100 МБ) або завантажуй кожен файл окремо. Внесок у спільноту – це легкий спосіб допомогти іншим та отримати додаткові можливості на сайті. Твої старі роботи можуть приносити тобі нові нагороди!
Нічого не вибрано
0%

Оголошення від адміністратора

Антиботан аватар за замовчуванням

Подякувати Студентському архіву довільною сумою

Admin

26.02.2023 12:38

Дякуємо, що користуєтесь нашим архівом!