Programowanie obiektowe /Java/ Laboratorium nr 6 1 Kompozycja Asocjacja (ang. association)1 Związek pomiędzy klasami obiektów (. . . ) Asocjacja może łączyć dwie lub więcej klas (niekoniecznie różnych). Zwykle uważa się, że asocjacja umożliwia przechodzenie (nawigację) pomiędzy powiązanymi nią obiektami w dowolnym kierunku. Agregacja (ang. aggregation)1 Związek pomiędzy klasami obiektów (szczególny przypadek asocjacji), modelujący stosunek całości do jej części (np. stosunek samochodu do silnika). Obiekty są powiązane związ- kiem agregacji, jeżeli jeden z nich można uważać za część drugiego, zaś cykl i czas życia tych obiektów są jednakowe. Kompozycja (ang. composition)1 Mocna forma agregacji wprowadzona w UML. Związek kompozycji oznacza, że dana część może należeć tylko do jednej całości. Co więcej, część nie może istnieć bez całości, pojawia się i jest usuwana razem z całością. Klasycznym przykładem związku kompozycji jest zamówienie i pozycja zamówienia: pozycja zamówienia nie występuje oddzielnie (poza zamówieniem), nie podlega prze- noszeniu od jednego zamówienia do innego zamówienia i znika w momencie kasowania zamówienia. 1 package pl.kielce.tu.lab6; 2 3 class Silnik { 4 void wlacz() { 5 System.out.println("Włączam silnik"); 6 } 7 } 8 9 class Podwozie { 10 void podnies() { 11 System.out.println("Podnoszę podwozie"); 12 } 13 } 14 15 public class Samolot { 16 Silnik s1 = new Silnik(); 17 Silnik s2 = new Silnik(); 18 Podwozie p = new Podwozie(); 19 20 void startuj() { 21 s1.wlacz(); 22 s2.wlacz(); 23 p.podnies(); 24 } 25 26 public static void main(String[] args) { 27 Samolot s = new Samolot(); 28 s.startuj(); 29 } 30 } Przykład 1: src/pl/kielce/tu/lab6/Samolot.java{link} 2 Dziedziczenie Dziedziczenie (ang. inheritance)1 - Związek pomiędzy klasami obiektów określający przekazywanie cech (definicji atrybutów, metod, itd.) z nadklasy do jej podklas np. obiekt klasy Pracownik dziedziczy wszystkie 1 Słownik terminów z zakresu obiektowości. K. Subieta, Akademicka Oficyna Wydawnicza PLJ, Warszawa 1999 1 własności (definicje atrybutów, metody) określone w ramach klasy Osoba. Dziedziczenie jest podstawowym mechanizmem sprzyjającym ponownemu użyciu. 1 package pl.kielce.tu.lab6; 2 3 class Urzadzenie { 4 void wlacz() { 5 System.out.println("Włączam urządzenie"); 6 } 7 8 void wylacz() { 9 System.out.println("Wyłączam urządzenie"); 10 } 11 } 12 13 public class Telefon extends Urzadzenie { 14 void dzwon() { 15 System.out.println("Dzwonię"); 16 } 17 18 public static void main(String[] args) { 19 Urzadzenie u = new Urzadzenie(); 20 u.wlacz(); 21 u.wylacz(); 22 Telefon k = new Telefon(); 23 k.wlacz(); 24 k.dzwon(); 25 k.wylacz(); 26 } 27 } Przykład 2: src/pl/kielce/tu/lab6/Telefon.java{link} Dziedziczenie w Javie: - można dziedziczyć tylko po jednej klasie bazowej, nie ma wielodziedziczenia (dziedziczenia wielobazo- wego), class X{} class Y{} public class Z extends X, Y {} //ERROR - jeśli nawet nie dziedziczymy1 bezpośrednio z innej klasy, to automatycznie dziedziczymy ze standar- dowej klasy bazowej o nazwie Object Po deasemblacji klasy X: Compiled from "X.java" class X extends java.lang.Object{ X(); } - super() wywołanie konstruktora klasy bazowej, - super.metoda(), super.atrybut dowołanie się do metody lub atrybutu klasy bazowej. Jeżeli w konstruktorze klasy pochodnej nie zostanie jawnie wywołany konstruktor klasy bazowej to kom- pilator spróbuje automatycznie wywołać bezargumentowy konstruktor klasy bazowej. 1 package pl.kielce.tu.lab6.inherit1; 2 3 class A { 2 4 A() { 5 System.out.println("A"); 6 } 7 } 8 9 public class B extends A { 10 11 B() { 12 System.out.println("B"); 13 } 14 15 public static void main(String[] args) { 16 B b = new B(); 17 } 18 } Przykład 3: src/pl/kielce/tu/lab6/inherit1/B.java{link} 1 package pl.kielce.tu.lab6.inherit2; 2 3 class A { 4 A(int i) { 5 System.out.println("A arg = " + i); 6 } 7 } 8 9 public class B extends A { 10 11 B() { 12 //ERROR 13 //Implicit super constructor A() is undefined. 14 //Must explicitly invoke another constructor. 15 System.out.println("B"); 16 } 17 18 B(int j) { 19 super(j + 1); 20 System.out.println("B arg = " + j); 21 } 22 23 public static void main(String[] args) { 24 B b = new B(); 25 } 26 } Przykład 4: src/pl/kielce/tu/lab6/inherit2/B.java{link} 1 package pl.kielce.tu.lab6.inherit3; 2 3 class A { 4 int i = 1; 5 6 int getI() { 7 return i; 8 } 9 10 String echo() { 11 return "A"; 12 } 13 14 String echo(String s) { 3 15 return "A:" + s; 16 } 17 } 18 19 public class B extends A { 20 int i = 2; 21 22 int getI() { 23 return i; 24 } 25 26 String echo() { 27 return "B"; 28 } 29 30 int superI() { 31 return super.i; 32 } 33 34 int superGetI() { 35 return super.getI(); 36 } 37 38 String superEcho() { 39 return super.echo(); 40 } 41 42 public static void main(String[] args) { 43 A x = new A(); 44 System.out.println(x.i + " " + x.getI() + " " + x.echo()); 45 B y = new B(); 46 System.out.println(y.i + " " + y.getI() + " " + y.echo() + " " + y.echo("???")); 47 System.out.println(y.superI() + " " + y.superGetI() + " " + y.superEcho()); 48 } 49 } Przykład 5: src/pl/kielce/tu/lab6/inherit3/B.java{link} 3 Delegacja Delegacja (ang. delegation)1 Określenie sytuacji w obiektowej strukturze danych, gdy operacje, które można wykonać na danym obiekcie, są własnością innego obiektu (są oddelegowane do innego obiektu). W nieco innym znaczeniu (UML) delegacją jest nazywana sytuacja, kiedy obiekt po otrzymaniu komunikatu wysyła komunikat do innego obiektu. Często określenie delegacja dotyczy sytuacji, kiedy jakiś złożony atry- but obiektu jest także obiektem i jest wystąpieniem innej klasy. Delegacja jest uważana także za alternatywę lub szczególny przypadek dziedziczenia. Komunikat (ang. message)1 Sygnał skierowany do obiektu wywołujący określoną metodę lub operację, którą należy wykonać na obiekcie. Komunikat może mieć parametry. Komunikat można uważać za wywoła- nie procedury związanej z obiektem, uruchamianej w środowisku (wewnątrz) obiektu i zdefiniowanej i/lub przechowywanej w ramach jego klasy i nadklas. 1 package pl.kielce.tu.lab6; 2 3 class Procesor { 4 void wykonajObliczenia() { 5 } 6 } 7 8 class Komputer { 9 private Procesor p = new Procesor(); 4 10 11 void wykonajObliczenia() { 12 p.wykonajObliczenia(); 13 } 14 15 public static void main(String[] args) { 16 Komputer k = new Komputer(); 17 k.wykonajObliczenia(); 18 } 19 } Przykład 6: src/pl/kielce/tu/lab6/Procesor.java{link} 4 Final Final2 ogólnie oznacza coś co nie może być zmienione . Możemy bowiem chcieć uniemożliwić dokony- wanie zmian z dwóch względów: projektowania lub wydajności. Ponieważ oba powody różnią się zasadniczo, słowo final może być stosowane niewłaściwie. Zmienne finalne - Dla typu elementarnego to wartość staje się stała, lecz dla referencji do obiektu to referencja zostaje stała. linie 17 i 19 w przykładzie 7. Przykłady inicjalizacji finalnych zmiennych statycznych: linie 9 i 12 w przykładzie 7. 1 package pl.kielce.tu.lab6.final1; 2 3 class MyFinal { 4 int i; 5 } 6 7 public class Final { 8 9 final static MyFinal f1 = new MyFinal(); 10 final static MyFinal f2; 11 static { 12 f2 = new MyFinal(); 13 } 14 15 public static void main(String[] args) { 16 final int i = 1; 17 i = 5; // ERROR 18 f1 = new MyFinal(); // ERROR 19 f1.i = 5; // OK !!! 20 } 21 } Przykład 7: src/pl/kielce/tu/lab6/final1/Final.java{link} Przykłady inicjalizacji finalnych zmiennych: linie 9, 12 i 17 w przykładzie 8. 1 package pl.kielce.tu.lab6.final2; 2 3 class MyFinal { 4 int i; 5 } 6 7 public class Final { 8 9 final MyFinal f1 = new MyFinal(); 10 final MyFinal f2; 2 Thinking in Java, Bruce Eckel, Wydanie IV, Helion, 2006 5 11 { 12 f2 = new MyFinal(); 13 } 14 final MyFinal f3; 15 16 Final() { 17 f3 = new MyFinal(); 18 } 19 20 public static void main(String[] args) { 21 Final f = new Final(); 22 } 23 } Przykład 8: src/pl/kielce/tu/lab6/final2/Final.java{link} 2 Metody finalne Po pierwsze jest to niejako założenie blokady na metodę, aby zabronić klasom po- chodnym jakichkolwiek zmian jest to podyktowane wymogami projektowymi, kiedy chcemy mieć pewność, że zachowanie metody zostanie niezmienione i nie będzie mogło być przesłonięte. Drugi powód stosowania metod finalnych jest związany z kwestią wydajności. (. . . ) 1 package pl.kielce.tu.lab6.final3; 2 3 class Final { 4 final void print() { 5 } 6 } 7 8 public class NewClass extends Final { 9 void print() { // ERROR 10 } 11 } Przykład 9: src/pl/kielce/tu/lab6/final3/NewClass.java{link} 2 Klasy finalne (. . . ) nie chcemy z niej dziedziczyć i również nie pozwalamy na to komukolwiek innemu. Innymi słowy, z jakichś powodów projekt klasy zakłada zakłada, że nigdy nie będzie potrzeby dokonywania żadnych zmian lub też ze względów bezpieczeństwa nie chcemy dalej dziedziczyć. 1 package pl.kielce.tu.lab6.final4; 2 3 final class Final { 4 final void print() { 5 } 6 } 7 8 public class NewClass extends Final { // ERROR 9 } Przykład 10: src/pl/kielce/tu/lab6/final4/NewClass.java{link} 5 Przekazywanie argumentów do programu 1 package pl.kielce.tu.lab6; 2 3 public class Params { 4 public static void main(String[] args) { 5 System.out.println("args.length = " + args.length); 6 for (int i = 0; i < args.length; i++) 7 System.out.println("args[" + i + "] = " + args[i]); 6 8 } 9 } Przykład 11: src/pl/kielce/tu/lab6/Params.java{link} Przykład uruchomienia: java ABC 123 XYZ args.length = 3 args[0] = ABC args[1] = 123 args[2] = XYZ 6 Przykładowa treść laboratorium Proszę stworzyć oraz uruchomić aplikację, w której zastosowana zostanie kompozycja, dziedziczenie oraz delegacja. 7