JAVA 06 Nieznany

background image

Programowanie obiektowe (Java) – 6

1

Dziedziczenie

Dziedziczenie (ang. inheritance) [7] - ”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
własności (definicje atrybutów, metody) określone w ramach klasy Osoba. Dziedziczenie jest podstawowym
mechanizmem sprzyjającym ponownemu użyciu.”

W Javie do oznaczania dziedziczenia klas wykorzystywane jest słowo kluczowe extends.

1

package

pl.kielce.tu.lab6;

2
3

class

Urzadzenie {

4

void

wlacz() {

5

System.out.println(

"Wyłączam urządzenie"

);

6

}

7
8

void

wylacz() {

9

System.out.println(

"Wyłączam urządzenie"

);

10

}

11

}

12
13

class

Telefon

extends

Urzadzenie {

14

void

dzwon() {

15

System.out.println(

"Dzwonię"

);

16

}

17

}

18
19

public class

TestInheritance {

20

public static void

main(String[] args) {

21

Urzadzenie u =

new

Urzadzenie();

22

u.wlacz();

23

u.wylacz();

24

Telefon k =

new

Telefon();

25

k.wlacz();

26

k.dzwon();

27

k.wylacz();

28

}

29

}

Przykład 1: src/pl/kielce/tu/lab6/TestInheritance.java {link}

1.1

Dziedziczenie z wykorzystaniem klas wewnętrznych

W Javie każda klasa można dziedziczyć tylko po jednej klasie bazowej, nie ma wielodziedziczenia klas

(dziedziczenia wielobazowego). Poniższy kod jest niepoprawny.

1

class

X{}

2

class

Y{}

3

public class

Z

extends

X, Y {}

//ERROR

Jeżeli klasa zawiera klasy wewnętrzne to każda z nich także może dziedziczyć po jednej klasie.

1

class

X{}

2

class

Y{}

3

public class

Z

extends

X {

4

class

ZY

extends

Y{}

5

}

1

background image

W połączeniu z możliwością dostępu przez klasy wewnętrzne do części prywatnej klasy zewnętrznej umoż-

liwia to uzyskanie zachowania częściowo zbliżonego do wielodziedziczenia klas:

1

package

pl.kielce.tu.lab6;

2
3

class

Ship {

4

private

String name;

5
6

Ship(String name) {

7

this

.name = name;

8

}

9

10

void

sail() {

11

System.out.println(

"The "

+ name +

" is sailing"

);

12

}

13

}

14
15

class

Car {

16

private

String name;

17
18

Car(String name) {

19

this

.name = name;

20

}

21
22

void

drive() {

23

System.out.println(

"The "

+ name +

" is driving"

);

24

}

25

}

26
27

class

Amphibian

extends

Ship {

28

private

AmphibianCar car;

29
30

Amphibian(String name) {

31

super

(name);

32

car =

new

AmphibianCar(name);

33

}

34
35

Ship transformIntoShip() {

36

return this

;

37

}

38
39

Car transformIntoCar() {

40

return

car;

41

}

42
43

public void

move(

boolean

water) {

44

if

(water) {

45

Ship s = transformIntoShip();

46

s.sail();

47

}

else

{

48

Car c = transformIntoCar();

49

c.drive();

50

}

51

}

52
53

private class

AmphibianCar

extends

Car {

54

AmphibianCar(String name) {

55

super

(name);

56

}

57

}

58

}

2

background image

59
60

public class

TestAmphibian {

61

public static void

main(String[] args) {

62

Amphibian a =

new

Amphibian(

"amphibian"

);

63

boolean

water =

true

;

64

a.move(water);

65

water =

false

;

66

a.move(water);

67
68

Car c = a.transformIntoCar();

69

c.drive();

70
71

Ship s = a.transformIntoShip();

72

s.sail();

73

}

74

}

Przykład 2: src/pl/kielce/tu/lab6/TestAmphibian.java {link}

1.2

Klasa java.lang.Object

Jeżeli dla klasy nie zostanie jawnie podana klasa, po której ma ona dziedziczyć, to jako klasa bazowa

zostanie użyta klasa java.lang.Object. Przykładowa klas X:

1

class

X{}

Po deasemblacji klasy X:

1

Compiled from

"X.java"

2

class

X

extends

java.lang.Object{

3

X();

4

}

Metody zdefiniowane w klasie java.lang.Object:

public

Object()

– konstruktor

protected

Object clone()

throws

CloneNotSupportedException

– zwraca kopie obiektu, metoda wykorzystywana podczas klonowania,

public boolean

equals(Object obj)

– służy do porównywania obiektów, nie chodzi tu o porównanie referencji (do tego służy ”==”) lecz
sprawdzenie równość (równoważności) obiektów na podstawie ich wartości,

Zasady tworzenia własnej metody equals(Object obj)

1

:

zwrotność (ang. reflexive): dla każdej referencji x różnej od null, wywołanie x.equals(x) powinno
zwrócić true,

symetryczność (ang. symmetric): dla wszystkich referencji x oraz y różnych od null, wywołanie
x.equals

(y) powinno zwrócić true wtedy i tylko wtedy jeżeli y.equals(x) też zwróci true,

przechodniość (ang. transitive): dla wszystkich referencji x, y oraz z różnych od null, jeżeli
x.equals

(y) zwraca true oraz y.equals(z) zwraca true, to x.equals(z) powinno też zwracać true,

1

http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#equals(java.lang.Object)

3

background image

spójność (ang. consistent): dla wszystkich referencji x, y oraz z różnych od null, wielokrotne
wywołanie x.equals(y) powinno zawsze zwracać true lub zawsze zwracać f alse, pod warunkiem,
że informacje wykorzystane do porównywania nie uległy w międzyczasie zmianie,

dla każdej referencji x różnej od null, wywołanie x.equals(null) powinno zwrócić f alse.

Zazwyczaj podczas przesłaniania metody equals() należy przesłonić metodę hashCode(). Związane to
jest z zachowaniem następującej zasady: jeżeli dwa obiekty są sobie równe (x.equals(y) zwraca true) to
mają także równe kody mieszające / haszujące (x.hashCode() == y.hashCode()).

Metoda equals(Object obj) posiada jeden parametr Objectobj. Oznacza to, że jeżeli w klasie Student
została przesłonięta metoda equals(Object obj) to porównywane będą dwa obiekty this (klasa Student)
oraz obj (klasa Object). W większości przypadków przed wykonaniem porównania konieczne będzie
wykonanie rzutowania (pkt. 2 oraz kolejne).

protected void

finalize()

throws

Throwable

– metoda wywoływana w trakcie odśmiecania, służy do finalizacji obiektu, czyli wykonania dodatkowych
czynności gdy obiekt jest usuwany,

public final

Class<?> getClass()

– zwraca klasę, do której należy obiekt,

1

public class

HelloWorld {

2

public static void

main(String[] args) {

3

HelloWorld h =

new

HelloWorld();

4

System.out.println(h.getClass() +

" has super "

+ h.getClass().getSuperclass());

5

Object o =

new

Object();

6

System.out.println(o.getClass() +

" has super "

+ o.getClass().getSuperclass());

7

}

8

}

public int

hashCode()

– zazwyczaj jej domyślna implementacja konwertuje wewnętrzny adres obiektu na int,

Zasady tworzenia metody hashCode()

2

:

jeżeli metoda ta wywoływana jest kilkukrotnie podczas działania aplikacji to musi zwracać ten sam
wynik, pod warunkiem że informacje wykorzystywane w metodzie equals() nie uległy zmianie, nie
jest konieczne, aby metoda zwracała taki sam wynik pomiędzy dwoma uruchomieniami aplikacji,

jeżeli dwa obiekty są równe zgodnie z metodą equals(), to wywołanie dla nich metody hashCode()
musi zwracać ten sam wynik,

jeżeli dwa obiekty nie są równe zgodnie z metodą equals(), to wywołanie dla nich metody
hashCode

() nie musi zwracać różnego wyniku.

Metoda System.identityHashCode(java.lang.Object obj) umożliwia pobranie wyniku dla domyślnej
metody hashCode(), niezależnie od tego czy metoda ta została przesłonięta czy nie.

public final void

notify()

public final void

notifyAll()

– metody służące do budzenia wątku lub wątków czekających na monitorze obiektu,

public

String toString()

2

http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#hashCode()

4

background image

– zwraca tekstową reprezentację obiektu, domyślnie jest to:

getClass().getName() +

'@'

+ Integer.toHexString(hashCode())

Zaleca się przesłonięcie tej metody we wszystkich klasach pochodnych. Metoda ta w połączeniu z kon-
struktorem z jednym parametrem typu tekstowego umożliwia stworzenie mechanizmu konwersji obiektu
na tekst oraz w odwrotną stronę. Przykład:

1

class

Student{

2

private

String imie, nazwisko, ulica;

3

int

numer;

4
5

Student(String imie, String nazwisko, String ulica,

int

numer){

6

this

.imie = imie;

7

this

.nazwisko = nazwisko;

8

this

.ulica = ulica;

9

this

.numer = numer;

10

}

11
12

Student(String text){

13

String [] tmp = text.split(

"#"

);

14

this

.imie = tmp[0];

15

this

.nazwisko = tmp[1];

16

this

.ulica = tmp[2];

17

this

.numer = Integer.valueOf(tmp[3]);

18

}

19
20

@Override

21

public

String toString(){

22

return

imie +

"#"

+ nazwisko +

"#"

+ ulica +

"#"

+ numer;

23

}

24

}

1

public class

TestStudent{

2

public static void

main(String [] args){

3

Student student =

new

Student(

"Jan"

,

"Kowalski"

,

"Al. 1000-lecia P. P."

, 7);

4

String text = student.toString();

5

Student student2 =

new

Student(text);

6

}

7

}

public final void

wait()

throws

InterruptedException

public final void

wait(

long

timeout)

throws

InterruptedException

public final void

wait(

long

timeout,

int

nanos)

throws

InterruptedException

– metody umożliwiające oczekiwanie aż wątek nie zostanie obudzony w wyniku wywołania metody
notify() lub notifyAll().

1.3

Final

Final[2] – „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.”

„Dla typu elementarnego to wartość staje się stała, lecz dla referencji do obiektu to referencja zostaje

stała.”

Metody finalne [2] – „Po pierwsze jest to niejako założenie blokady na metodę, aby zabronić klasom

pochodnym jakichkolwiek zmian – jest to podyktowane wymogami projektowymi, kiedy chcemy mieć pewność,

5

background image

ż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. (. . . )”

Klasy finalne [2] – „(. . . ) 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, że nigdy nie będzie potrzeby dokonywania żadnych
zmian lub też ze względów bezpieczeństwa nie chcemy dalej dziedziczyć.”

1.3.1

Finalne atrybuty

Atrybuty finalne statyczne muszą zostać zainicjalizowane w momencie deklarowania (linia 8 w przykładach

3 i 4) lub w bloku inicjalizacji egzemplarza (linia 14 w przykładach 3 i 4).

1

public class

Final1 {

2
3

class

MyFinal {

4

}

5
6

final static

MyFinal f1 =

new

MyFinal();

7

final static

MyFinal f2;

8

final static

MyFinal f3;

// error: The blank field f3 might not have been initialized

9

final static

MyFinal f4;

// error: The blank field f4 might not have been initialized

10
11

static

{

12

f2 =

new

MyFinal();

13

}

14
15

public static void

main(String[] args) {

16

f3 =

new

MyFinal();

// error: The final field f3 can not be assigned

17

}

18

}

Przykład 3: src/pl/kielce/tu/lab6/finals/Final1.java {link}

1

public class

Final2 {

2
3

class

MyFinal {

4

}

5
6

final static int

f1 = 1;

7

final static int

f2;

8

final static int

f3;

// error: The blank field f3 might not have been initialized

9

final static int

f4;

// error: The blank field f4 might not have been initialized

10
11

static

{

12

f2 = 1;

13

}

14
15

public static void

main(String[] args) {

16

f3 = 2;

// error: The final field f3 can not be assigned

17

}

18

}

Przykład 4: src/pl/kielce/tu/lab6/finals/Final2.java {link}

Atrybuty finalne niestatyczne muszą zostać zainicjalizowane w momencie deklarowania (linia 8 w przy-

kładach 5 i 6), w bloku inicjalizacji egzemplarza (linia 14 w przykładach 5 i 6) lub w konstruktorze (linia 18
w przykładach 5 i 6).

1

public class

Final3 {

2
3

class

MyFinal {

4

}

6

background image

5
6

final

MyFinal f1 =

new

MyFinal();

7

final

MyFinal f2;

8

final

MyFinal f3;

9

final

MyFinal f4;

// error: The blank field f4 might not have been initialized

10
11

{

12

f2 =

new

MyFinal();

13

}

14
15

Final3() {

16

f3 =

new

MyFinal();

17

}

18

}

Przykład 5: src/pl/kielce/tu/lab6/finals/Final3.java {link}

1

public class

Final4 {

2
3

class

MyFinal {

4

}

5
6

final int

f1 = 1;

7

final int

f2;

8

final int

f3;

9

final int

f4;

// error: The blank field f4 might not have been initialized

10
11

{

12

f2 = 2;

13

}

14
15

Final4() {

16

f3 = 3;

17

}

18

}

Przykład 6: src/pl/kielce/tu/lab6/finals/Final4.java {link}

1.3.2

Finalne zmienne lokalne

Zmienne lokalne, które zostały oznaczone jako finalne muszą zostać zainacjalizowane w momencie dekla-

racji i od tego momentu nie można pod nie przypisywać nowej wartości.

1.3.3

Finalne parametry metod

Pod parametry metod oznaczone jako finalne nie może być przypisane nowa wartość.

1

public class

Final5 {

2
3

static void

test1(

int

i) {

4

i++;

5

System.out.println(

"test1(): "

+ i);

6

}

7
8

static void

test2(

final int

i) {

9

i++;

// error: The final local variable can not be assigned.

10

System.out.println(

"test1(): "

+ i);

11

}

12
13

public static void

main(String[] args) {

14

int

j = 1;

7

background image

15

System.out.println(

"main(): "

+ j);

16

test1(j);

17

System.out.println(

"main(): "

+ j);

18

System.out.println();

19
20

System.out.println(

"main(): "

+ j);

21

test2(j);

22

System.out.println(

"main(): "

+ j);

23

System.out.println();

24

}

25

}

Przykład 7: src/pl/kielce/tu/lab6/finals/Final5.java {link}

1

public class

Final6 {

2
3

static void

test1(Final6 f) {

4

f =

new

Final6();

5

System.out.println(

"test1(): "

+ f);

6

}

7
8

static void

test2(

final

Final6 f) {

9

f =

new

Final6();

// error: The final local variable can not be assigned.

10

System.out.println(

"test1(): "

+ f);

11

}

12
13

public static void

main(String[] args) {

14

Final6 f =

new

Final6();

15

System.out.println(

"main(): "

+ f);

16

test1(f);

17

System.out.println(

"main(): "

+ f);

18

System.out.println();

19
20

System.out.println(

"main(): "

+ f);

21

test2(f);

22

System.out.println(

"main(): "

+ f);

23

System.out.println();

24

}

25

}

Przykład 8: src/pl/kielce/tu/lab6/finals/Final6.java {link}

1.3.4

Finalne metody

1

class

MyFinalMethod {

2

final public void

method() {

3

}

4

}

5
6

class

MyFinalMethod2

extends

MyFinalMethod {

7

// error: method() in MyFinal2 cannot override method() in MyFinal

8

public void

method() {

9

}

10

}

Przykład 9: src/pl/kielce/tu/lab6/finals/Final7.java {link}

1.3.5

Finalne klasy

8

background image

1

final class

MyFinalClass {

2

}

3
4

// error: cannot inherit from final MyFinal

5

class

MyFinalClass2

extends

MyFinalClass {

6

}

Przykład 10: src/pl/kielce/tu/lab6/finals/Final8.java {link}

2

Rzutowanie

Kast (ang. cast) [7] – „Termin C, C++ i innych interfejsów oznaczający operator konwersji typu. Zwykle

przyjmuje postać nazwy typu w nawiasach okrągłych, stawianej przed wielkością podlegającą konwersji typu.”
Kast w dół (ang. downcast) - „Konwersja typu na typ stojący niżej w hierarchii (na podtyp).” Kast w górę
(ang. upcast) - „Konwersja typu na typ stojący wyżej w hierarchii (na nadtyp).”

1

package

pl.kielce.tu.lab6;

2
3

class

Pojazd {}

4
5

class

Samochod

extends

Pojazd {}

6
7

class

Motocykl

extends

Pojazd {}

8
9

public class

TestCast {

10

public static void

main(String[] args) {

11

Pojazd[] p =

new

Pojazd[2];

12

// poniżej rzutowanie w górę

13

p[0] =

new

Samochod();

14

p[1] =

new

Motocykl();

15

// poniżej poprawne rzutowanie w dół

16

Samochod s = (Samochod) p[0];

17

Motocykl m = (Motocykl) p[1];

18

// poniżej niepoprawne rzutowanie w dół

19

// java.lang.ClassCastException

20

Motocykl m2 = (Motocykl) p[0];

21

// java.lang.ClassCastException

22

Samochod s2 = (Samochod) p[1];

23

}

24

}

Przykład 11: src/pl/kielce/tu/lab6/TestCast.java {link}

2.1

Operator instanceOf

Operator instanceof zwraca prawdę jeśli obiekt można rzutować na podany typ.

1

public class

TestInstanceOf {

2
3

static

Random r =

new

Random();

4
5

public static

Object makeNew() {

6

switch

(r.nextInt() % 2) {

7

case

0:

8

return new

String(

"TEST"

);

9

default

:

10

return new

Integer(123);

11

}

9

background image

12

}

13
14

public static void

main(String[] args)

throws

Exception {

15

for

(

int

j = 0; j < 10; j++) {

16

Object o = makeNew();

17

if

(o

instanceof

String) {

18

String s = (String) o;

19

System.out.println(

"String == "

+ o.getClass().getSimpleName() +

" "

+ ←֓

s.toLowerCase());

20

}

else if

(o

instanceof

Integer) {

21

Integer i = (Integer) o;

22

System.out.println(

"Integer == "

+ o.getClass().getSimpleName() +

" "

+ ←֓

i.floatValue());

23

}

else

{

24

throw new

RuntimeException(

"Object of unknown class"

);

25

}

26

}

27

}

28

}

Przykład 12: src/pl/kielce/tu/lab6/TestInstanceOf.java {link}

2.2

Metoda isInstance

()

„Metoda isInstance() klasy Class pozwala na dynamiczne testowanie typu obiektu.”

1

public class

TestIsInstance {

2
3

static

Random r =

new

Random();

4
5

public static

Object makeNew() {

6

switch

(r.nextInt() % 2) {

7

case

0:

8

return new

String(

"TEST"

);

9

default

:

10

return new

Integer(123);

11

}

12

}

13
14

public static void

main(String[] args)

throws

Exception {

15

for

(

int

j = 0; j < 10; j++) {

16

Object o = makeNew();

17

if

(String.

class

.isInstance(o)) {

18

String s = (String) o;

19

System.out.println(

"String == "

+ o.getClass().getSimpleName() +

" "

+ ←֓

s.toLowerCase());

20

}

else if

(Integer.

class

.isInstance(o)) {

21

Integer i = (Integer) o;

22

System.out.println(

"Integer == "

+ o.getClass().getSimpleName() +

" "

+ ←֓

i.floatValue());

23

}

else

{

24

throw new

RuntimeException(

"Object of unknown class"

);

25

}

26

}

27

}

28

}

Przykład 13: src/pl/kielce/tu/lab6/TestIsInstance.java {link}

10

background image

3

Polimorfizm

Polimorfizm (ang. polymorphism) [7] – „Termin używany w dwóch nieco różnych znaczeniach (które są

często mylone):

• (1) w terminologii obiektowej: możliwość istnienia wielu metod o tej samej nazwie, powiązana z możli-

wością wyboru konkretnej metody podczas czasu wykonania (dynamicznym wiązaniem);

• (2) w terminologii teorii typów i języków polimorficznych (np. w ML): umożliwienie definiowania funkcji

lub procedur, których argumenty i wynik mogą posiadać jednocześnie wiele typów;”

Statyczne wiązanie (ang. static binding) [7] – „Wiązanie nazw występujących w programie, które ma

miejsce podczas kompilacji.”

Wiązanie dynamiczne (ang. dynamic binding) [7] – „Wiązanie nazw występujących w programie na etapie

wykonania programu; inaczej późne wiązanie.”

Wywołania polimorficzne metod dotyczą tylko metod niestatycznych, natomiast nie dotyczą metod sta-

tycznych oraz operacji dostępu (odczytu / zapisu) do atrybutów zarówno statycznych jak i niestatycznych.
Dostęp do atrybutów oraz metod statycznych powinien być realizowany poprzez klasę, do której należą, np.
Klasa.atrybutStatyczny lub Klasa.metodaStatyczna(). Możliwy jest dostęp poprzez: obiekt.atrybutStatyczny
lub obiekt.metodaStatyczna(). Jest on jednak niezalecany i jego zastosowanie powodujący wydrukowanie
ostrzeżenia podczas kompilacji.

1

package

pl.kielce.tu.lab6;

2
3

class

A {

4

public

String field =

"A"

;

5

public static

String staticField =

"A"

;

6
7

public void

test() {

8

System.out.println(

"A.test()"

);

9

}

10
11

public static void

testStatic() {

12

System.out.println(

"A.testStatic()"

);

13

}

14

}

15
16

class

B

extends

A {

17

public

String field =

"B"

;

18

public static

String staticField =

"B"

;

19
20

public void

test() {

21

System.out.println(

"B.test()"

);

22

}

23
24

public static void

testStatic() {

25

System.out.println(

"B.testStatic()"

);

26

}

27

}

28
29

public class

TestPolymorphism {

30

private final static

String nl = System.getProperty(

"line.separator"

);

31
32

public static void

main(String[] args) {

33

A a =

new

A();

34

a.test();

35

// Warning: the static method testStatic() from the type A should be accessed

36

// in a static way

37

a.testStatic();

38

// Warning: the static field A.testStatic() should be accessed in a static way

39

System.out.println(

"field = "

+ a.field +

", staticField = "

+ a.staticField + nl);

11

background image

40
41

B b =

new

B();

42

b.test();

43

// Warning: the static method testStatic() from the type B should be accessed

44

// in a static way

45

b.testStatic();

46

// Warning: the static field B.testStatic() should be accessed in a static way

47

System.out.println(

"field = "

+ b.field +

", staticField = "

+ b.staticField + nl);

48
49

A ab =

new

B();

50

ab.test();

51

// Warning: the static method testStatic() from the type A should be accessed

52

// in a static way

53

ab.testStatic();

54

// Warning: the static field A.testStatic() should be accessed in a static way

55

System.out.println(

"field = "

+ ab.field +

", staticField = "

+ ab.staticField + nl);

56

}

57

}

Przykład 14: src/pl/kielce/tu/lab6/TestPolymorphism.java {link}

4

Przesłanianie i przeciążanie

4.1

Przesłanianie

Przesłanianie (ang. overriding) [7] – „Odnosi się do sytuacji, kiedy implementacje funkcji (procedur,

operatorów, metod) posiadających tę samą nazwę występują na różnych poziomach hierarchii dziedziczenia
(co najmniej dwóch). W tej sytuacji do obiektu stosuje się funkcję znajdującą się najniżej w części hierarchii
od korzenia do klasy tego obiektu; pozostałe funkcje o tej samej nazwie (z klas bardziej ogólnych, nadklas)
są ’przesłonięte’ przez tę funkcję. Przesłanianie jest realizacją strategii określanej jako ’pojedyncza dyspozy-
cja’ (ang. single dispatching) i jest ściśle powiązane z polimorfizmem. Przesłanianie wymaga dynamicznego
wiązania i jest jednym z ważnych elementów wspomagających ponowne użycie (ang. reuse).”

4.2

Przeciążanie

Przeciążanie (ang. overloading) [7] – „Sytuacja, w której ta sama nazwa (lub symbol) jest użyta do

oznaczenia dwóch lub więcej funkcji (procedur, operatorów lub metod), zaś rozstrzygnięcie tej homonimii
następuje na podstawie kontekstu jej użycia (np. typu lub liczby argumentów operacji).”

4.3

Adnotacja @Override

„Zapis @Override [2] chroni nas przed przypadkowym przeciążeniem tam, gdzie chodzi nam o przesłonię-

cie.” Co stanie się jeżeli linia 23 z adnotacją @Override zostanie odkomentowana?

1

class

Calculator {

2

// przeciążenie printSum(int i, int j, int k, int l, int m, boolean b)

3

void

printSum() {

4

System.out.println(

"Calculator.printSum()"

);

5

}

6
7

// przeciążenie printSum()

8

void

printSum(

int

i,

int

j,

int

k,

int

l,

int

m,

boolean

b) {

9

System.out.println(

"Calculator.printSum(int i, int j, int k, int l, int m, boolean b)"

);

10

}

11

}

12
13

class

Calculator2

extends

Calculator {

14

// przesłonięcie printSum()

15

@Override

12

background image

16

void

printSum() {

17

System.out.println(

"Calculator2.printSum()"

);

18

}

19
20

// przeciążenie czy przesłonięcie ???

21

// @Override

22

void

printSum(

int

i,

int

j,

int

k,

int

l,

boolean

b) {

23

System.out.println(

"printSum(int i, int j, int k, int l, boolean b)"

);

24

}

25

}

Przykład 15: src/pl/kielce/tu/lab6/TestOverride.java {link}

4.4

Kowariancja typów zwracanych

Przesłonięta metoda klasy pochodnej [2] może zwracać typ pochodny względem typu zwracanego przez

metodę bazową. W przykładzie poniżej proszę porównać typy zwracane przez metody potomek() oraz two-
rzenie obiektów k1-k2 i p1-p2.

1

package

pl.kielce.tu.lab6;

2
3

class

Zwierze {

4

void

odglos() {

5

System.out.println(

"???"

);

6

}

7
8

void

dzwiek(

int

iloscPowtorzen) {

9

for

(

int

i = 0; i < iloscPowtorzen; i++)

10

odglos();

11

}

12
13

Zwierze potomek() {

14

return new

Zwierze();

15

}

16

}

17
18

class

Kot

extends

Zwierze {

19

@Override

20

void

odglos() {

21

System.out.println(

"Miau"

);

22

}

23
24

@Override

25

Kot potomek() {

26

return new

Kot();

27

}

28

}

29
30

class

Pies

extends

Zwierze {

31

@Override

32

void

odglos() {

33

System.out.println(

"Hau"

);

34

}

35
36

@Override

37

Pies potomek() {

38

return new

Pies();

39

}

40

}

41
42

public class

TestCovariance {

13

background image

43

public static void

main(String[] args) {

44

Zwierze z1 =

new

Kot();

45

Zwierze z2 =

new

Pies();

46
47

// Type missmatch: can not convert from Zwierze to Kot

48

// Kot k1 = z1.potomek();

49

Kot k1 = (Kot) z1.potomek();

50

// Type missmatch: can not convert from Zwierze to Pies

51

// Pies p1 = z2.potomek();

52

Pies p1 = (Pies) z2.potomek();

53
54

Kot k2 = k1.potomek();

55

Pies p2 = p1.potomek();

56

}

57

}

Przykład 16: src/pl/kielce/tu/lab6/TestCovariance.java {link}

5

Przykładowa treść laboratorium

1. Na stronach 16 oraz 18 znajdują się definicje klasy M yHashCollection oraz T estM yCollection. Klasa

M yHashCollection

w uproszczony sposób przedstawia działanie kolekcji haszującej (mieszającej) z eli-

minacją obiektów o tej samej wartości. Zawiera ona tablicę kubełków (ang. bucket) należących do klasy
M yBucket

. Podczas dodania lub usunięcia obiektu z kolekcji najpierw wyliczana jest wartość funkcji

haszującej (mieszającej) dla obiektu. Następnie na podstawie funkcji reszty z dzielenia wyznaczany
jest numer kubełka, do którego należy dodać (usunąć) obiekt. W klasie T estM yCollection w metodzie
testIntegers

() do kolekcji są dodawane i usuwane liczby. Program działa zgodnie z założeniami. Obiek-

ty o tej samej wartości dodawane są tylko raz. Poprawnie działa także usuwanie obiektów. Celem tego
zadania jest uzyskanie takiego samego zachowania dla metody testStudentsAndT eachers():

• wielokrotne dodanie różnych obiektów o takich samych polach powinno spowodować dodanie obiek-

tu tylko raz,

• usunięcie obiektu powinno być możliwe także poprzez podanie innego obiektu, ale posiadającego

takie same pola.

Modyfikować można tylko klasy P erson, Student oraz T eacher. Oczekiwany wynik działania programu
znajduje się na str. 20 .

2. Proszę stworzyć rozbudowaną hierarchię klas dotyczącą komponentów graficznych, takich jak Okna,

Panele, Przyciski, ListyWyboru, itp. W tym zadaniu powinny pojawić się przykłady:

• dziedziczenia, w tym także dziedziczenia z wykorzystaniem klas wewnętrznych,

• przeciążania i przesłaniania metod zdefiniowanych we własnych klasach oraz klasie Object, adno-

tacji @Override,

• rzutowania w górę (na klasę bazową) i w dół (na klasę pochodną), wykorzystania operatora in-

stanceOf lub metody isInstance(),

• wszystkich zastosowań słowa kluczowego final.

3. Inne

Literatura

[1] Schildt Herbert, Java. Kompendium programisty. Wydanie VIII, Helion, 2012

[2] Eckel Bruce, Thinking in Java, Edycja polska, Wydanie IV, Helion, 2006

[3] Horstmann Cay S., Cornell Gary, Java. Podstawy, Wydanie VIII, Helion, 2008

14

background image

[4] Horstmann Cay S., Cornell Gary, Java. Techniki zaawansowane, Wydanie VIII, Helion, 2009

[5] Bloch Joshua, Java. Efektywne programowanie. Wydanie II, Helion, 2009

[6] Brackeen David, Barker Bret, Vanhelsuwe Laurence, Java. Tworzenie gier, Helion, 2004

[7] Słownik terminów z zakresu obiektowości. Kazimierz Subieta, Akademicka Oficyna Wydawnicza PLJ,

Warszawa 1999

[8] Sedgewick Robert, Wayne Kevin, Algorytmy. Wydanie IV, Helion, 2012

Materiały

do

przedmiotu

dostępne

na

stronach:

http://achilles.tu.kielce.pl/

http://weaii-

moodle.tu.kielce.pl/

15

background image

Klasa MyHashCollection

package

pl.kielce.tu.lab6;

public class

MyHashCollection {

private

MyBucket[] buckets;

private int

bucketsQuantity;

public

MyHashCollection(

int

bucketsQuantity,

int

bucketCapacity) {

this

.bucketsQuantity = bucketsQuantity;

this

.buckets =

new

MyBucket[bucketsQuantity];

for

(

int

i = 0; i < bucketsQuantity; i++)

this

.buckets[i] =

new

MyBucket(bucketCapacity);

}

/**

* Adds the object only when it does not exists in the collection
*
* @param obj
* the object which should be added
* @return true if the object was added, and false otherwise
*/

public boolean

add(Object obj) {

int

hashCode = obj.hashCode();

int

bucketNumber = hashCode % bucketsQuantity;

return

buckets[bucketNumber].add(obj);

}

/**

* Deletes object from the collection
*
* @param obj
* the object which should be deleted
* @return true if the object was deleted, and false otherwise
*/

public boolean

delete(Object obj) {

int

hashCode = obj.hashCode();

int

bucketNumber = hashCode % bucketsQuantity;

return

buckets[bucketNumber].delete(obj);

}

@Override

public

String toString() {

String answer =

"["

;

for

(

int

i = 0; i < buckets.length; i++) {

answer += buckets[i];

if

(i != buckets.length - 1)

answer +=

", "

;

}
answer +=

"]"

;

return

answer;

}

private class

MyBucket {

final private static int

NONE = -1;

private

Object[] objects;

public

MyBucket(

int

bucketCapacity) {

objects =

new

Object[bucketCapacity];

}

16

background image

/**

* Adds the object only when it does not exists in the bucket
*
* @param obj
* the object which should be added
* @return true if the object was added, and false otherwise
*/

public boolean

add(Object obj) {

int

empty = NONE;

for

(

int

i = 0; i < objects.length; i++) {

// checks whether there is an empty space

if

(empty == NONE && objects[i] ==

null

)

empty = i;

// checks whether the object already was added

if

(objects[i] !=

null

&& objects[i].equals(obj))

return false

;

}

// not empty space

if

(empty == NONE)

return false

;

// adds object

objects[empty] = obj;

return true

;

}

/**

* Deletes object from the bucket
*
* @param obj
* the object which should be deleted
* @return true if the object was deleted, and false otherwise
*/

public boolean

delete(Object obj) {

for

(

int

i = 0; i < objects.length; i++) {

// checks whether the object was added

if

(objects[i] !=

null

&& objects[i].equals(obj)) {

objects[i] =

null

;

return true

;

}

}

return false

;

}

@Override

public

String toString() {

String answer =

"["

;

for

(

int

i = 0; i < objects.length; i++) {

answer += objects[i] !=

null

? objects[i] :

"_"

;

if

(i != objects.length - 1)

answer +=

", "

;

}
answer +=

"]"

;

return

answer;

}

}

}

Przykład 17: src/pl/kielce/tu/lab6/MyHashCollection.java {link}

17

background image

Klasa TestMyCollection

package

pl.kielce.tu.lab6;

class

Person {

int

id;

String firstName, lastName;

Person(

int

id, String firstName, String lastName) {

this

.id = id;

this

.firstName = firstName;

this

.lastName = lastName;

}

}

class

Student

extends

Person {

String group;

Student(

int

id, String firstName, String lastName, String group) {

super

(id, firstName, lastName);

this

.group = group;

}

}

class

Teacher

extends

Person {

String title;

Teacher(

int

id, String title, String firstName, String lastName) {

super

(id, firstName, lastName);

this

.title = title;

}

}

public class

TestMyCollection {

private static void

testIntegers() {

MyHashCollection list =

new

MyHashCollection(4, 4);

list.add(1);
list.add(1);
list.add(9);
list.add(2);
list.add(3);
System.out.println(list);
list.delete(3);
System.out.println(list);
list.add(5);
System.out.println(list);

}

private static void

testStudentsAndTeachers() {

MyHashCollection list =

new

MyHashCollection(4, 4);

list.add(

new

Student(1,

"Jan"

,

"Kowalski"

,

"Group_1"

));

list.add(

new

Student(1,

"Jan"

,

"Kowalski"

,

"Group_1"

));

list.add(

new

Teacher(9,

"prof."

,

"Adam"

,

"Mickiewicz"

));

list.add(

new

Student(2,

"Piotr"

,

"Nowak"

,

"Group_1"

));

list.add(

new

Student(3,

"Tomasz"

,

"Kowal"

,

"Group_1"

));

System.out.println(list);
list.delete(

new

Student(3,

"Piotr"

,

"Nowak"

,

"Group_1"

));

System.out.println(list);
list.add(

new

Student(5,

"Wojciech"

,

"Król"

,

"Group_1"

));

System.out.println(list);

18

background image

}

public static void

main(String[] args) {

testIntegers();
testStudentsAndTeachers();

}

}

Przykład 18: src/pl/kielce/tu/lab6/TestMyCollection.java {link}

19

background image

Aktualny wynik działania programu:

1

[[_, _, _, _], [1, 9, _, _], [2, _, _, _], [3, _, _, _]]

2

[[_, _, _, _], [1, 9, _, _], [2, _, _, _], [_, _, _, _]]

3

[[_, _, _, _], [1, 9, 5, _], [2, _, _, _], [_, _, _, _]]

4

[[S1, S2, S3, _], [T9, _, _, _], [_, _, _, _], [S1, _, _, _]]

5

[[S1, S2, S3, _], [T9, _, _, _], [_, _, _, _], [S1, _, _, _]]

6

[[S1, S2, S3, _], [T9, S5, _, _], [_, _, _, _], [S1, _, _, _]]

Oczekiwany wynik działania programu:

1

[[_, _, _, _], [1, 9, _, _], [2, _, _, _], [3, _, _, _]]

2

[[_, _, _, _], [1, 9, _, _], [2, _, _, _], [_, _, _, _]]

3

[[_, _, _, _], [1, 9, 5, _], [2, _, _, _], [_, _, _, _]]

4

[[_, _, _, _], [S1, T9, _, _], [S2, _, _, _], [S3, _, _, _]]

5

[[_, _, _, _], [S1, T9, _, _], [S2, _, _, _], [_, _, _, _]]

6

[[_, _, _, _], [S1, T9, S5, _], [S2, _, _, _], [_, _, _, _]]

20


Document Outline


Wyszukiwarka

Podobne podstrony:
EPII Majatek trwaly v 2010 06 2 Nieznany
materia ey Zarz udzanie BHP, 06 Nieznany
Misterium Zmartwychwstania 06 Nieznany
Biologia zapylania roslin I 06 Nieznany (2)
facade (fasada) [java wzorce p Nieznany
JAVA 10 Nieznany
JAVA 06 wejście i wyjście
JAVA 08 Nieznany
JAVA 09 Nieznany
Opracowane pytania z Testu Java 06
podstawy programowania java id Nieznany
Biofizyka kontrolka do cw nr 06 Nieznany (2)
Java 06 Klasy Interfejsy
EPII Majatek trwaly v 2010 06 2 Nieznany
materia ey Zarz udzanie BHP, 06 Nieznany
java 06
java 06
pkt 06 ST id 360232 Nieznany

więcej podobnych podstron