Interfejsy, klasy wewn trzne jako szczególny rodzaj obiektów Robert A. Kªopotek r.klopotek@uksw.edu.pl Wydziaª Matematyczno-Przyrodniczy. Szkoªa Nauk cisªych, UKSW 16.03.2017
Interfejsy raz jeszcze "Interfejsy i klasy abstrakcyjne to strukturalizowane ±rodki oddzielenia interfejsu od implementacji" w C++ obsªuguje si je jedynie po±rednio w Java s obecne jawnie, poniewa» zostaªy uznane za dostatecznie wa»ne obsªugiwane s bezpo±rednio przez sªowa kluczowe j zyka Java klasy abstrakcyjne s po±redni postaci pomi dzy zwykªymi klasami a interfejsami 2 / 26
Klasy abstrakcyjne obiekty klasy abstrakcyjnej, prawie zawsze nie maj konkretnego znaczenia klas abstrakcyjn tworzymy, gdy chcemy manipulowa zestawem klas pochodnych poprzez wspólny interfejs metoda abstrakcyjna - zawiera tylko deklaracj, nie posiada ciaªa, np. abstract void f(); (w C++ jest to podobne do metody czysto wirtualnej, np. virtual void f() = 0;) klasa zawieraj ca metody abstrakcyjne nazywana jest klas abstrakcyjn je±li klasa ma co najmniej jedn metod abstrakcyjn to musi by zadeklarowana z u»yciem modykatora abstract - inaczej kompilator zgªosi bª d 3 / 26
Klasy abstrakcyjne - wªasno±ci przy próbie stworzenia obiektu klasy abstrakcyjnej kompilator zwróci bª d - nie musimy si martwi o jej nieprawidªowe u»ycie je±li dziedziczymy po klasie abstrakcyjnej to musimy dostarczy denicje wszystkich metod abstrakcyjnych klasy bazowej je±li tego nie zrobimy, nowa klasa stanie si równie» abstrakcyjna i kompilator b dzie nas zmuszaª do u»ycia modykatora abstract mo»na zadeklarowa klas jako abstrakcyjn je±li nie ma metod abstrakcyjnych - jest to przydatne je±li chcemy zapobiec utworzeniu obiektu naszej klasy klasy abstrakcyjne s przydatnymi narz dziami refaktoryzacji kodu, bo pozwalaj na ªatwiejsze przenoszenie metod w gór hierarchii dziedziczenia 4 / 26
Interfejsy vs klasy abstrakcyjne sªowo kluczowe abstract pozwala na tworzenie jednej lub wielu metod niezdeniowanych - ustanowienie interfejsu bez udost pniania odpowiadaj cej mu implementacji implementacj metod abstrakcyjnych maja dostarczy klasy dziedzicz ce sªowo kluczowe interface generuje zupeªnie abstrakcyjna klas bazow, która jest caªkowicie pozbawiona implementacji (niestety nie jest to ju» do ko«ca prawda w Java 8) klasa typu interface pozwala nam ustanowi nazwy metod, listy argumentów, typy zwracane - jednak bez ciaªa metod (nowo± w Java 8 - metody default oraz static z ciaªem) kod u»ywaj cy danego interfejsu wie, jakie metody mog by wywoªywane dla danego interfejsu i to wszystko 5 / 26
Interfejsy - wªasno±ci interfejs pozwala na realizacj pewnej odmiany "dziedziczenia wielobazowego" - rzutowanie w gór na wi cej ni» jeden typ bazowy aby stworzy interfejs musimy u»y sªowa kluczowego interface! zamiast class w interfejsie mo»emy deklarowa pola - s one traktowane jako static final je±li interfejs ma modykator public to jego wszystkie pola i metody maja modykator public, mimo i» tego nie napiszemy aby stworzy dany interfejs lub grup interfejsów u»ywamy sªowa kluczowego implements poza tymi ró»nicami realizacja interfejsu wygl da tak jak dziedziczenie 6 / 26
Interfejs - przykªad // plik Samochód. java public interface Samochód { public void jed¹ (); public void zaªó»naczep (); // plik AbstrakcyjnySamochód.java public abstract class AbstrakcyjnySamochód implements Samochód { public void jed¹ () { // kod odpowiedzialny za poruszanie si samochodu public abstract void zaªó»naczep (); // plik Ferrari.java public class Ferrari extends AbstrakcyjnySamochód { public void zaªó»naczep () { // nic nie robimy. Ferrari nie mo»e mie naczepy // plik Star.java public class Star extends AbstrakcyjnySamochód { public void zaªó»naczep () { // Czynno±ci zwi zane z zakªadaniem naczepy 7 / 26
"Dziedziczenie wielobazowe" w Javie interfejs nie posiadaª»adnej implementacji - nie byªa z nim zwi zana pami, wi c nic nie staªo na przeszkodzie, aby poª czy wiele interfejsów (Java 8 du»o tu popsuªa) w C++ ª czenie interfejsów wielu klas nazywane jest wielokrotnym dziedziczeniem i stwarza wiele problemów, poniewa» klasa mo»e mie implementacj w Javie mo»emy dokona czego± podobnego, jednak tylko jedna z klas mogªa mie implementacj, wiec problemy z ª czeniem wielu klas nie wyst powaªy (od Java 8 ju» wyst puj ) klasa pochodna nie musi mie abstrakcyjnej lub "konkretnej" klasy bazowej je±li dziedziczymy po klasie, a nie po interfejsie, to mo»e by to tylko jedna klasa, wszystkie inne elementy musza by interfejsami 8 / 26
Dziedziczenie rozª czne 9 / 26
Dziedziczenie po klasie abstrakcyjnej 10 / 26
"Dziedziczenie wielobazowe" 11 / 26
Interfejsy - metody domy±lne w Java 8 dodano nowa funkcjonalno± do interfejsu - metody domy±lne (default methods) metody domy±lne pozwalaj zdeniowa ciaªo metody w interfejsie, zachowujemy mo»liwo± wielokrotnego dziedziczenia klasa implementuj ca interfejs nie musi implementowa metod, które maj domy±ln implementacj przykªadowy interfejs z metod domy±ln wygl da nast puj co public interface Prioritized { public default int getpriority () { return 0; przykªad pozwala stosowa ten interfejs jako "marker", bez konieczno±ci implementacji metody, która w wi kszo±ci przypadków wygl daªaby identycznie 12 / 26
Interfejsy - Java 8 UWAGA: o ile Java dopuszcza wielokrotne dziedziczenie interfejsów, i jest to mo»liwe tak»e z metodami domy±lnymi, to w sytuacji koniktu (dwa interfejsy posiadaj ce metod domy±ln ) wyst pi bª d kompilacji metody domy±lne nie mog te» przysªania metod obiektów metoda obiektu zawsze "wygrywa" z metod domy±ln i to ona (metoda obiektu) jest uruchamiana klasy abstrakcyjne mog dziedziczy tylko po jednej innej klasie, mog dostarcza ciaªa metod i mog okre±la metody o innej widoczno±ci ni» public interfejsy mog by dziedziczone wielokrotnie, mog dostarcza domy±lne ciaªa metod (ale nie mog przesªania innych metod) i dotycz tylko metod o widoczno±ci public 13 / 26
Interfejsy - kiedy stosowa? je±li mo»liwe jest stworzenie klasy bazowej bez zdeniowania»adnych metod lub zmiennych skªadowych, powinni±my zawsze wybiera interfejsy, a nie klasy abstrakcyjne w zasadzie, je±li wiemy,»e co± b dzie jedynie klasa bazow, naszym pierwszym wyborem powinno by zdeniowanie tego jako interfejs kolizje podczas ª czenia interfejsów - wykorzystanie takich samych nazw metod w ró»nych interfejsach, przeznaczonych do ª czenia ze sob powoduje zamieszania i zmniejsza czytelno± (spaghetti code) - nale»y tego unika 14 / 26
Klasy wewn trzne "Java pozwala na osadzanie denicji klasy w obr bie denicji innej klasy. Mowa wtedy o klasie wewn trznej" klasy wewn trzne umo»liwiaj grupowanie logicznie ze sob powi zanych klas i kontrolowanie widoczno±ci jednych w drugich klasa wewn trzna ma wiedze o klasie otaczaj cej i mo»e si z ni komunikowa klasy wewn trzne tworzy si poprzez umieszczenie ich denicji w otaczaj cej klasie je±li chcemy stworzy obiekt klasy wewn trznej gdziekolwiek poza wn trzem metody klasy zewn trznej, typ obiektu musimy poda jako NazwaKlasyZewn trznej.nazwaklasyzagnie»dzonej 15 / 26
Poª czenie z klas zewn trzn po stworzeniu obiekt klasy wewn trznej zawiera specjalny ª cznik z obiektem klasy zewn trznej, który go stworzyª taki obiekt ma dost p do skªadowych otaczaj cego obiektu bez»adnej specjalnej kwalikacji klasy wewn trzne posiadaj prawo dost pu do wszystkich elementów klasy je otaczaj cej w C++ klasy zagnie»d»one byªy po prostu mechanizmem ukrywania nazw, nie miaªy one ª cznika ani domy±lnych praw dost pu do skªadowych 16 / 26
Klasa wewn trzna - przykªad public class OuterClass { public class InnerClass { public InnerClass intantiate () { return new InnerClass (); Tworzenie klasy wewn trznej: private static void innerclassinstantiation () { OuterClass outerclass = new OuterClass (); OuterClass. InnerClass instance1 = outerclass. intantiate (); OuterClass. InnerClass instance2 = outerclass. new InnerClass (); 17 / 26
Statyczna klasa wewn trzna - przykªad public class OuterClass2 { public static class InnerClass2 { private InnerClass2 instantiate () { return new InnerClass2 (); Tworzenie statycznej klasy wewn trznej: private static void staticinnerclassinstantiation () { OuterClass2 outerclass = new OuterClass2 (); OuterClass2. InnerClass2 instance1 = outerclass. instantiate (); OuterClass2. InnerClass2 instance2 = new OuterClass2. InnerClass2 (); 18 / 26
Lokalna klasa wewn trzna - przykªad private static void localclassinstantiation ( String [] args ) { class LocalClass { @Override public String tostring () { return " Argumenty metody : " + Arrays. tostring ( args ); LocalClass localclassinstance = new LocalClass (); System. out. println ( localclassinstance ); 19 / 26
Jak to dziaªa? egzemplarz klasy wewn trznej musi przechowywa referencj do konkretnego obiektu klasy j zawieraj cego - tego, który stworzyª jej instancj podczas odnoszenia si dl skªadnika klasy otaczaj cej, ta referencja jest wykorzystywana do wybrania go ten do± skomplikowany proces kompilator bierze na siebie my musimy pami ta,»e obiekt klasy wewn trznej mo»e by stworzony jedynie w powi zaniu z obiektem klasy j zawieraj cej (o ile ta klasa nie jest statyczna) konstrukcja obiektu klasy wewn trznej wymaga referencji do obiektu klasy zewn trznej, a kompilator zaprotestuje, je±li nie b dzie mógª tej referencji osta 20 / 26
.this i.new kiedy potrzebna nam jest referencja do klasy zewn trznej to mo»na j wygenerowa za pomoc instrukcji NazwaKlasyZewn trznej.this niekiedy trzeba poinstruowa inny obiekt o konieczno±ci utworzenie obiektu jednej z jego klas wewn trznych - wtedy zamiast operatora new nale»y poda referencj obiektu klasy zewn trznej za po±rednictwem napisu.new (patrz przykªad) aby wprost odnie± si do klasy wewn trznej, nale»y odnie± si w kwalikacji nie do nazwy klasy zewn trznej tylko do nazwy obiektu klasy zewn trznej private static void innerclassinstantiation () { OuterClass outerclass = new OuterClass (); OuterClass. InnerClass instance1 = outerclass. intantiate (); OuterClass. InnerClass instance2 = outerclass. new InnerClass (); 21 / 26
Klasy anonimowe w zasadzie powinna si nazywa wewn trzna klasa anonimowa klasy anonimowe to klasy deniowane w kodzie, które maj dokªadnie jedn instancj denicja klasy anonimowej poª czona jest z tworzeniem jej jedynej instancji klasy anonimowe zawsze s klasami wewn trznymi wewn trz denicji klasy anonimowej mo»emy deniowa atrybuty czy metody - w praktyce sprowadza si to przewa»nie do zaimplementowania metod interfejsu dla którego tworzymy klas anonimow 22 / 26
Klasy anonimowe - przykªad 1 import java. util. Arrays ; import java. util. Comparator ; public class Porównywarka { public static void main ( String [] args ) { String [] obiekty = {" zamek ", " nó» ", " samochód ", " auto " ; Arrays. sort ( obiekty ); System. out. println ( Arrays. tostring ( obiekty )); // [ auto, nó», samochód, zamek ] Arrays. sort ( obiekty, new Comparator < String >() { @Override public int compare ( String o1, String o2 ) { return o1. length () > o2. length ()? 1 : -1; ); System. out. println ( Arrays. tostring ( obiekty )); // [ nó», auto, zamek, samochód ] 23 / 26
Klasy anonimowe - przykªad 2 (1/2) public class KlasaAnonimowa { public static class Samochód { private final Opis opis ; public Samochód ( Opis opis ){ this. opis = opis ; public void wyswietl (){ opis. wypisz (); public interface Opis { void wypisz (); 24 / 26
Klasy anonimowe - przykªad 2 (2/2) public class KlasaAnonimowa { public static void main ( String [] args ) { Samochód bmw = new Samochód ( new Opis () { @Override public void wypisz () { System. out. println (" To jest BMW " ); ); Samochód opel = new Samochód ( new Opis () { @Override public void wypisz () { System. out. println (" To jest Opel " ); ); bmw. wyswietl (); opel. wyswietl (); 25 / 26
26 / 26 Pytania?