Ponowne wykorzystanie klas

Slides:



Advertisements
Podobne prezentacje
Temat 2: Podstawy programowania Algorytmy – 1 z 2 _________________________________________________________________________________________________________________.
Advertisements

Typy i metody sparametryzowane (generics) (c) Krzysztof Barteczko 2014.
Proces doboru próby. Badana populacja – (zbiorowość generalna, populacja generalna) ogół rzeczywistych jednostek, o których chcemy uzyskać informacje.
Tworzenie odwołania zewnętrznego (łącza) do zakresu komórek w innym skoroszycie Możliwości efektywnego stosowania odwołań zewnętrznych Odwołania zewnętrzne.
Wyszukiwanie informacji w Internecie. Czym jest wyszukiwarka? INTERNET ZASOBY ZAINDEKSOWANE PRZEZ WYSZUKIWARKI Wyszukiwarka to mechanizm, który za pomocą.
OBSŁUGA KARTY DILO. Karta diagnostyki i leczenia onkologicznego zawiera: - oznaczenie pacjenta, pozwalające na ustalenie jego tożsamości, - oznaczenie.
Zmienne losowe Zmienne losowe oznacza się dużymi literami alfabetu łacińskiego, na przykład X, Y, Z. Natomiast wartości jakie one przyjmują odpowiednio.
„Książki nie mają właściwości róż, dlatego nie szukajmy wciąż najświeższych”
Komunikatory Zespół Szkół Zawodowych Nr 3 im. Adama Kocura w Katowicach - Janowie.
Python. Języki Programistyczne Microcode Machine code Assembly Language (symboliczna reprezentacja machine code) Low-level Programming Language (FORTRAN,
Świat mówi o Bogu. CELE : Na dzisiejszych zajęciach: dowiesz się czy o istnieniu Boga można mieć pewną wiedzę czy też mamy w Niego tylko wierzyć.
Optymalna wielkość produkcji przedsiębiorstwa działającego w doskonałej konkurencji (analiza krótkookresowa) Przypomnijmy założenia modelu doskonałej.
Definiowanie i planowanie zadań typu P 1.  Planowanie zadań typu P  Zadania typu P to zadania unikalne służące zwykle dokonaniu jednorazowej, konkretnej.
PORADNIK WPROWADZANIA AKCJI. OGÓLNIE: Akcja musi zostać utworzona i opublikowana co najmniej tydzień przed jej rozpoczęciem. W opisie muszą znajdować.
Język Java Paweł Rajba
Dziedziczenie, polimorfizm, Interfejsy
Programowanie Obiektowe – Wykład 6
Test analizy wariancji dla wielu średnich – klasyfikacja pojedyncza
Rola książki w życiu człowieka
Programowanie Obiektowe – Wykład 1
Kluczowe elementy skutecznej strategii analizy danych internetowych
O ochronie danych osobowych
Schematy blokowe.
Kurs języka C++ – wykład 2 ( )
DEFINICJA I ZASTOSOWANIE W JĘZYKU HASKELL
Rachunki zdań Tautologiczność funkcji
Logarytmy.
Full Text Finder Przegląd Publication Finder
Liczby pierwsze.
Części składowe treści pisma
Akademia C# - Lab2 Zmienne, instrukcje warunkowe, pętle, debugger,
Kurs języka C++ – wykład 6 ( )
(c) Krzysztof Barteczko 2014
Rekursje Tak jak w innych językach funkcje mogą odwoływać się same do siebie Możemy regulować głębokość przed stwierdzeniem błędu (MaxRecursion, $RecursionLimit,
(c) Krzysztof Barteczko 2014
Akademia C# lab. 9 Zdarzenia i delegaty.
Programowanie Obiektowe – Wykład 2
Programowanie obiektowe
Wstęp do Informatyki - Wykład 3
Budowa, typologia, funkcjonalność
Optymalizacja programów Open-Source
Przewodnik Udoskonalanie listy wyników w wyszukiwarce naukowej
Lekcja 1 – Hello World! Visual Studio, coś łatwego na początek 
Klasy wewnętrzne. Praktyka użycia interfejsów i klas wewnętrznych
Programowanie obiektowe
Materiały pochodzą z Platformy Edukacyjnej Portalu
Materiały pochodzą z Platformy Edukacyjnej Portalu
Kurs języka C++ – wykład 13 ( )
Języki programowania.
Programowanie obiektowe
Laboratorium 1 – obsługa wejść i wyjść
Pojęcie i skład spadku.
Koszyk danych.
Podstawy informatyki Zygfryd Głowacz.
Programowanie obiektowe Wykład 11
Strukturalne wzorce projektowe
Zmienne i typy danych w C#
Iteracyjno-rozwojowy cykl oprogramowania 2
Proste obliczenia w arkuszu kalkulacyjnym
FORMUŁOWANIE HIPOTEZ STATYSTYCZNYCH
Zdarzenia (eventy) Zdarzenia służą do powiadomienia użytkownika, gdy w używanej klasie dojdzie do pewnych wydarzeń zdefiniowanych przez twórcę klasy.
Implementacja rekurencji w języku Haskell
Znajdowanie liczb pierwszych w zbiorze
Język C++ Preprocesor Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi i Pawła.
Język C++ Operatory Łukasz Sztangret Katedra Informatyki Stosowanej i Modelowania Prezentacja przygotowana w oparciu o materiały Danuty Szeligi i Pawła.
Kwerendy funkcjonalne (Action queries)
Program na dziś Wprowadzenie Logika prezentacji i artykułu
Negocjacje - Cień przyszłości
Zawsze słyszymy o „zasadach” ze strony kobiet
Zapis prezentacji:

Ponowne wykorzystanie klas (c) Krzysztof Barteczko 2014

Rodzaje ponownego wykorzystania (c) Krzysztof Barteczko 2014

Dziedziczenie - koncepcja Dziedziczenie polega na przejęciu właściwości i funkcjonalności obiektów innej klasy i ewentualnej ich  modyfikacji i/lub uzupelnieniu w taki sposób, by były one bardziej wyspecjalizowane. Jest to relacja, nazywana generalizacją-specjalizacją:  B "jest typu" A, "B jest A", a jednocześnie B specjalizuje A. A jest generalizacją B. (c) Krzysztof Barteczko 2014

Zacznijmy dziedziczyć Niech klasa Publication, opisuje właściwości publikacji, które kupuje i sprzedaje księgarnia: public class Publication { private String title; private String publisher; private int year; private String ident; private double price; private int quantity; public Publication() { } public Publication(String t, String pb, int y, tring i, double pr, int q) { title = t; publisher = pb; year = y; ident = i; price = pr; quantity = q; } public String getTitle() { return title; public String getPublisher() { return publisher; public int getYear() { return year; } public String getIdent() { return ident; public double getPrice() { return price; public void setPrice(double p) { price = p; public int getQuantity() { return quantity; public void buy(int n) { quantity += n; public void sell(int n) { quantity -= n; Za pomocą tej klasy nie możemy w pełni opisać książek. Książki są szczególną, "wyspecjalizowaną" wersją publikacji. Więc powinniśmy stworzyć nową klasę opisującą książki, o nazwie np. Book. Moglibyśmy to robić od podstaw Ale po co? (c) Krzysztof Barteczko 2014

Składnia dla dziedziczenia (c) Krzysztof Barteczko 2014

(c) Krzysztof Barteczko 2014 Klasa Book public class Book extends Publication { private String author; public Book(String aut, String tit, String pub, int y, String id, double price, int quant) { super(tit, pub, y, id, price, quant); author = aut; } public Book() { public String getAuthor() { return author; Użycie  w konstruktorze następującej konstrukcji składniowej:         super(lista_argumentów); oznacza wywołanie konstruktora klasy bazowej z argumentami lista_argumentów. Jeśli występuje - MUSI być pierwszą instrukcją konstruktora klasy pochodnej. Jeśli nie występuje - przed utworzeniem obiektu klasy pochodnej zostanie wywołany konstruktor bezparametrowy klasy bazowej. (c) Krzysztof Barteczko 2014

(c) Krzysztof Barteczko 2014 Tytuł Przy tak zdefiniowanej klasie Book możemy utworzyć jej obiekt: Book b = new Book("James Gossling", "Moja Java", "WNT", 2002, "ISBN6893", 51.0, 0); (c) Krzysztof Barteczko 2014

Jeśli B extends A, to B jest A (c) Krzysztof Barteczko 2014

Rozszerzające konwersje refrencyjne (c) Krzysztof Barteczko 2014

Znaczenie konwersji rozszerzających (c) Krzysztof Barteczko 2014

(c) Krzysztof Barteczko 2014 Problem 1 (c) Krzysztof Barteczko 2014

Referencyjne konwersje zawężające (c) Krzysztof Barteczko 2014

(c) Krzysztof Barteczko 2014 Problem 2 Co by się jednak stało, gdyby tej metodzie przekazać  obiekt klasy Journal? Kompilator nie będzie protestował, bo Journal pochodzi od Publication. W fazie kompilacji nie jest też możiwe sprawdzenie co tak naprawdę siedzi w zmiennej p1, czy to jest referencja do obiektu klasy Book czy też może jakiejś innej klasy pochodnej od Publication. Prawda wyjdzie na jaw dopiero w fazie wykonania programu: rzutowanie do typu Book spowoduje błąd o nazwie ClassCastException i przerwanie programu, ponieważ w p1 znajduje się referencja do obiektu klasy Journal i nie da się jej rzutować na referencję do obiektu typu Book. (c) Krzysztof Barteczko 2014

Stwierdzanie typu - operator instanceof (c) Krzysztof Barteczko 2014

(c) Krzysztof Barteczko 2014 Użycie instanceof (c) Krzysztof Barteczko 2014

Stwierdzanie typu – getClass() Metoda getClass() zwraca faktyczny typ obiektu w postaci referencji do obiektu klasy Class. Obiekty tej klasy oznaczają klasy. W kontekście: Book b = new Book(...); Publication p = b; Class c = p.getClass(); zmienna c będzie oznaczać klasę Book. Łatwo możemy się dowiedzieć o nazwę klasy: Class klasa = p.getClass(); String nazwa = klasa.getName();   i w ten sposób sprawdzić o jaką klasę chodzi. Przy takim sprawdzaniu można też użyć tzw. literałów klasowych. Mają one postać: nazwa_klasy.class  (c) Krzysztof Barteczko 2014

instanceof a getClass - różnica Załóżmy, że mamy jeszcze dodatkowo klasę Tabloid, dziedzicząca klasę Journal  i obiekt tej klasy: Tabloid t = new Tabloid(...); Wtedy: t instanceof Journal zwróci true, bo brane są pod uwagę wszystkie podtypy Journal, a t jest typu Tabloid czyli podtypu Journal, natomiast t.getClass() == Journal.class będzie miało wartość false, bo sprawdzana jest konkretna klasa, którą w tym przypadku jest Tabloid.   Oczywiście,  t.getClass().getName() zwróci napis "Tabloid". (c) Krzysztof Barteczko 2014

Cechy dziedziczenia w Javie W Javie każda klasa może bezpośrednio odziedziczyć tylko jedną klasę. Ale pośrednio może mieć dowolnie wiele nadklas, co wynika z hierarchii dziedziczenia. Ta hierarchia zawsze zaczyna się na klasie Object (której definicja znajduje się w zestawie stanardowych klas Javy). Zatem w Javie wszystkie klasy pochodzą pośrednio od klasy Object. Jeśli definiując klasę nie użyjemy słowa extends (nie zażądamy jawnie dziedziczenia), to i tak nasza klasa domyślnie będzie dziedziczyć klasę Object (tak jakbyśmy napisali class A extends Object). Z tego wynika, że: referencję do obiektu dowolnej klasy można przypisać zmiennej typu Object (c) Krzysztof Barteczko 2014

Przedefiniowanie metod (c) Krzysztof Barteczko 2014

(c) Krzysztof Barteczko 2014 Klasa Car class Car extends Vehicle { private String nrRej; private int tankCapacity; private int fuel; public Car(String nr, Person owner, int w, int h, int l, int weight, int tankCap) { super(owner, w, h, l, weight); nrRej = nr; tankCapacity = tankCap; } public void fill(int amount) { fuel += amount; if (fuel > tankCapacity) fuel = tankCapacity; public void start() { if (fuel > 0) super.start(); else error("Brak paliwa"); public String toString() { return "Samochód nr rej " + nrRej + " - " + getState(); (c) Krzysztof Barteczko 2014

Przedefiniowanie metod - definicja (c) Krzysztof Barteczko 2014

Wywoływanie przedefiniowanych metod z nadklasy (c) Krzysztof Barteczko 2014

(c) Krzysztof Barteczko 2014 Użycie Wobec obiektów klasy Car możemy używać:  wszystkich nieprywatnych (i nieprzedefiniowanych) metod klasy Vehicle (np. crash(...)),  przedefiniowanych w klasie Car metod klasy Vehicle, własnych metod klasy Car. Car c = new Car("WA1090", new Person("Janek", "09090909"), 100, 100, 100, 100, 50), d = new Car("WB2010", new Person("Ania", "10101010"), 100, 100, 100, 100, 50); try { c.start(); } catch (Exception exc) { System.out.println(c + " - " + exc.getMessage()); } c.fill(10); System.out.println(c); c.stop(); d.fill(20); System.out.println(d); d.start(); c.crash(d); System.out.println(c + "\n" + d); c.repair(); d.repair(); Samochód nr rej WA1090 - STOPPED - Brak paliwa Samochód nr rej WA1090 - STOPPED Samochód nr rej WA1090 - MOVING Samochód nr rej WB2010 - STOPPED Samochód nr rej WB2010 - MOVING Samochód nr rej WA1090 - BROKEN Samochód nr rej WB2010 - BROKEN (c) Krzysztof Barteczko 2014

(c) Krzysztof Barteczko 2014 Zwracajmy this (c) Krzysztof Barteczko 2014

Kowariantne typy wyników   W sytuacji: class A {   S met() {...} } class B extends A {  T met() {...} } metoda met ma kowariantny typ wyniku, jeśli T jest podtypem S. Kowariancja znaczy "współzmienność" - typ wyniku metody zmienia się w tym samym kierunku hierarchii dziedziczenia, jak kierunek dziedziczenia klas, w których jest definiowana. Typy wyników metod przedefiniowanych mogą być kowariantne. (c) Krzysztof Barteczko 2014

Użycie kowariantnych typów wyników (c) Krzysztof Barteczko 2014

Przedefiniowanie metod w wyliczeniach public enum VehState { BROKEN("ZEPSUTY"), STOPPED("STOI"), MOVING("JEDZIE"); private String opis; VehState(String s) { opis = s; } public String toString() { return opis; } } amochód nr rej WA1090 - ZEPSUTY Samochód nr rej WB2010 - ZEPSUTY Samochód nr rej WA1090 - JEDZIE Samochód nr rej WB2010 - JEDZIE (c) Krzysztof Barteczko 2014

Przedefiniowując metody używajmy @Override (c) Krzysztof Barteczko 2014

Jak są wywoływane przedefiniowane metody? (c) Krzysztof Barteczko 2014

(c) Krzysztof Barteczko 2014 Metody wirtualne Decyduje faktyczny typ: Jak to możliwe? Kompilator nie zna faktycznego typu: public static void main(String args[]) { Car c = new Car(...); Rydwan r = new Rydwan(...); Vehicle v; if (args[0].equals("Rydwan")) v = r; else v = c; v.start(); } Metoda start() z klasy Vehicle jest metodą wirtualną, a dla takich metod wiązanie odwołań z kodem następuje w fazie wykonania,  a nie w fazie kompilacji. Nazywa się to  "dynamic binding" lub "late binding". (c) Krzysztof Barteczko 2014

(c) Krzysztof Barteczko 2014 Polimorfizm (c) Krzysztof Barteczko 2014

Przykład polimorfizmu – hierarchia klas zwierząt class Zwierz { String name = "bez imienia"; Zwierz() { } Zwierz(String s) { name = s; } String getTyp() { return "Jakis zwierz"; } String getName() { return name; } String getVoice() { return "?"; } // Metoda speak symuluje wydanie głosu poprzez wypisanie odpowiedniego komunikatu void speak() { System.out.println(getTyp()+" "+getName()+" mówi "+getVoice()); } class Pies extends Zwierz { Pies() { } Pies(String s) { super(s); } String getTyp() { return "Pies"; } String getVoice() { return "HAU, HAU!"; } class Kot extends Zwierz { Kot() { } Kot(String s) { super(s); } String getTyp() { return "Kot"; } String getVoice() { return "Miauuuu..."; } (c) Krzysztof Barteczko 2014

Przykład polimorfizmu – rozmowy zwierząt static void animalDialog(Zwierz z1, Zwierz z2) { z1.speak(); z2.speak(); System.out.println("----------------------------------------"); } // ... Zwierz z1 = new Zwierz(), z2 = new Zwierz(); Pies pies = new Pies(), kuba = new Pies("Kuba"), reksio = new Pies("Reksio"); Kot kot = new Kot(); animalDialog(z1, z2); animalDialog(kuba, reksio); animalDialog(kuba, kot); animalDialog(reksio, pies); Jakis zwierz bez imienia mówi ? ---------------------------------------- Pies Kuba mówi HAU, HAU! Pies Reksio mówi HAU, HAU! Kot bez imienia mówi Miauuuu... Pies bez imienia mówi HAU, HAU! (c) Krzysztof Barteczko 2014

Znaczenie polimorfizmu Dzięki wirtualności metod getTyp() i getVoice() metoda speak(), określona w klasie Zwierz prawidłowo działa dla różnych zwierząt (obiektów podklas klasy Zwierz). Jedna definicja metody speak() załatwiła nam wszystkie potrzeby (dotyczące dialogów różnych zwerząt). Co więcej – będzie ona tak samo użyteczna dla każdej nowej podklasy Zwierza, którą kiedykolwiek w przyszłości wprowadzimy. (c) Krzysztof Barteczko 2014

Polimorfizm na codzień (c) Krzysztof Barteczko 2014

(c) Krzysztof Barteczko 2014 Kompozycja Z koncepcyjnego punktu widzenia kompozycja oznacza, że "obiekt jest zawarty w innym obiekcie”. Jest to relacja "całość – część"  ( B "zawiera" A).  Np. obiekty typu Biurko zawierają obiekty typu Szuflada. Robimy to bez przerwy, np. stosując w klasach pola typu String. (c) Krzysztof Barteczko 2014

(c) Krzysztof Barteczko 2014 Delegowanie odwołań class Text {   // ...   String cont;   // ...   String getCont() { return cont; } } Text txt = new Text(...); aby uzyskać długość tekstu musimy napisać:     txt.getCont().length(); "Skrót", który można dostarczyć polega na zdefiniowaniu w klasie Text metody length(): public int length() { return cont.length(); } Taki rodzaj definicji nazywa się delegowaniem wywołań metod. Teraz możemy pisać prościej: txt.length(); W różnych środowiskach uruchomieniowych delegowanie odwołań przy kompozycji jest łatwe, bowiem zapewniona jest automatyczna generacja kodu na podstawie naszych wyborów z dialogów. DEMO. (c) Krzysztof Barteczko 2014

Kompozycja a dziedziczenie Kompozycja ma czasem przewagę nad dziedziczeniem, ponieważ dziedziczenie może prowadzić do tzw. „słabej hermetyzacji kodu klasy bazowej” (demo z treści wykladu). REGUŁA Należy dostosowywać sposób ponownego wykorzystania do dziedziny problemu. Dziedziczenia używamy tylko wtedy, kiedy spełniona jest relacja "B jest A”. Czasem okazuje się, że taka relacja jest pozorna lub może ulegać zmianom w cyklu życiowym obiektów. Dobrym testem jest postawienie pytania czy zawsze, w każdych okolicznościach działania naszego programu można sensownie myśleć o rozszerzającej konwersji referencyjnej typu podklasy do typu nadklasy. (c) Krzysztof Barteczko 2014