Java


6. Klasy pochodne i interfejsy

6.1. Rozszerzanie klas

Języki obiektowo zorientowane (obiektowe) stały się standardem ze względu na następujące zalety:

W języku obiektowo zorientowanym świat jest zbiorem obiektów pogrupowanych w klasy.


0x08 graphic
0x08 graphic
0x08 graphic
0x08 graphic
0x08 graphic
0x08 graphic
0x08 graphic
0x08 graphic
0x08 graphic
0x08 graphic
0x08 graphic

0x08 graphic
0x08 graphic
0x08 graphic
0x08 graphic
0x08 graphic
0x08 graphic
0x08 graphic
0x08 graphic
0x08 graphic
0x08 graphic
0x08 graphic


Podstawową cechą hierarchicznego opisu obiektów jest zasada dziedzi­cze­nia: wszystkie własności opisane na wyższym poziomie obowiązują również na poziomach niższych.

Informację o tym, że dana klasa jest potomną (rozszerzeniem) innej klasy, wprowadzamy za pomocą słowa kluczowego extends:

Przykład:

class Student extends Osoba {

int nrIndeksu;

static int liczbaStudentów = 0;

final static String JESTEM = "Jestem student ";

final static String INDEKS = ", mam indeks Nr ";

Student ( String imię, String nazwisko ) {

super ( imię, nazwisko, NIEZNANE );

nrIndeksu = ++liczbaStudentów;

}

Student ( String imię, String nazwisko, String nrTel ) {

super ( imię, nazwisko, nrTel );

nrIndeksu = ++liczbaStudentów;

}

void jestem ( ) {

System.out.println ( JESTEM+ imię + " "
+ nazwisko + INDEKS + nrIndeksu );

}

Zgodnie z zasadą dziedziczenia cechy imię i nazwisko przechodzą do klasy potomnej Student. W klasie tej wprowadzamy jedynie cechę wyróżniającą studenta − numer jego indeksu.

Podobnie jak słowo kluczowe this oznaczało dany obiekt, słowo super odsyła do klasy nadrzędnej. W konstruktorze obiektu klasy Student widzimy zatem odwołanie do konstruktora klasy Osoba.

W klasie potomnej Student użyliśmy tej samej nazwy jestem dla metody wyświetlającej dane obiektu, co w klasie bazowej Osoba. Jednakże metoda klasy potomnej daje inny wynik, niż metoda klasy bazowej. Takie postępowanie nazywamy przesłanianiem metody (patrz rysunek).

Chcąc wykorzystać w klasie potomnej wersję pierwotną metody jestem musimy do niej odwołać się poprzez słowo kluczowe super. Możemy przy tym nadal używać nazwy jestem, lecz musimy zmienić sygnaturę. Takie postępowanie nazywamy przeciążaniem metody. Poniższy przykład pokazuje przeciążanie metody jestem :

void jestem ( String nrTel ) {

super.jestem ( );

}

Widzimy tu odwołanie do oryginalnej wersji tej metody przechowywanej w klasie Osoba.

Jeżeli utworzymy obiekt

Student s = new Student ( "Jan", "Kowalski" );

i wywołamy jego metodę prezentacji

s.jestem ( );

to otrzymamy napis

Jestem student Jan Kowalski, mam indeks Nr 1

Natomiast instrukcja

s.jestem ( nrTel );

wyświetli napis

Jestem Jan Kowalski, tel. ??? , mam Nr 1

zgodnie z definicją metody jestem podaną w klasie Osoba.

6.2. Pakiety

Pisząc w Javie większy program wygodnie pogrupować klasy w grupy zwane pakietami. W tym celu w pierwszym wierszu zbioru źródłowego podajemy nazwę pakietu, np.:

package ludzie;

class Osoba {

// opis klasy

}

class Student {

// opis klasy

}

Każda klasa w Javie jest częścią jakiegoś pakietu. Jeżeli nie określimy nazwy pakietu deklaracją package, to klasa zostanie przypisana do domyślnego pakietu bez nazwy.

Tekst źródłowy i kod bajtowy klasy należącej do pakietu nienazwanego powinny się znajdować w katalogu bieżącym (classpath = . ), a odpo­wiednie zbiory dla klas należących do pakietu nazwanego − w podkata­logu o nazwie zgodnej z nazwą pakietu.

Na przykład, jeżeli katalogiem bieżącym jest

C:\Java\Programy

to klasy Osoba będziemy szukali w katalogu

C:\Java\Programy\ludzie

W razie potrzeby, można poinformować kompilator i interpreter, gdzie znajdują się teksty źródłowe i kody bajtowe klas:

Dodatkową zaletą podziału klas na pakiety jest zmniejszenie ryzyka konfliktu nazw. Załóżmy, że chcemy skorzystać z opracowanej przez kogoś bazy danych osobowych, której klasy należą do pakietu baza. W tym celu wystarczy zaimportować ten pakiet:

import baza;

Okazuje się jednak, że w pakiecie tym jest również klasa Osoba, nie mająca wiele wspólnego z klasą o tej samej nazwie z pakietu ludzie. W takim przypadku kompilator nie pozwoli nam utworzyć obiektu

Osoba os = new Osoba ("Jan", "Kowalski");

Trzeba będzie określić dokładnie, o klasę z którego pakietu chodzi:

ludzie.Osoba os = new ludzie.Osoba ("Jan", "Kowalski");

Pakiety mogą być zagnieżdżane, np.

kadry.płace.pracownicy_etatowi.Pracownik

jest odwołaniem do klasy Pracownik, która należy do pakietu pracownicy_etatowi, zagnieżdzonego w pakietach płace i kadry.

Podobnie jak inne nowoczesne języki, Java daje użytkownikowi bogaty zestaw gotowych klas. Można je znaleźć w bibliotece klas java. Należą do niej następujące pakiety:

Importować można określoną klasę, np.

import ludzie.Student;

lub wszystkie klasy pakietu:

import ludzie.*;

W przeciwieństwie do znanego z C polecenia #include , importowanie klas w Javie odbywa się dynamicznie: interpretator ładuje do pamięci tylko te klasy, które są potrzebne przy wykonywaniu programu.

6.3. Kontrola dostępu

Wewnątrz klasy są zawsze dostępne zmienne, stałe i metody zadeklarowane w tej klasie. Natomiast widoczność i dziedziczenie pomiędzy klasami i pakietami regulują modyfikatory dostępu:

public

widoczne wszędzie, gdzie widoczna jest dana klasa, i dziedziczone przez wszystkie jej klasy potomne

private

widoczne tylko w ramach danej klasy

protected

widoczne w danym pakiecie i dziedziczone przez klasy potomne

(package)

elementy bez modyfikatorów dostępu są widoczne w danym pakiecie i dziedziczone przez klasy potomne z tego samego pakietu

Widzialność elementów można ująć dodatkowo w takiej tabeli:

Widoczne

public

protected

package

private

wewnątrz danej klasy

tak

tak

tak

tak

w każdej klasie tego samego pakietu

tak

tak

tak

nie

w każdej klasie potomnej umieszczonej w tym samym pakiecie

tak

tak

tak

nie

w każdej klasie potomnej umieszczonej w innym pakiecie

tak

tak

nie

nie

w klasie z innego pakietu

tak

nie

nie

nie

Skutecznym środkiem budowy programów odpornych na błędy i łatwych w utrzymaniu jest ograniczanie dostępu do wnętrza modułów:

0x08 graphic
0x08 graphic
0x08 graphic
0x08 graphic
0x08 graphic

0x08 graphic
0x08 graphic
0x08 graphic
0x08 graphic
0x08 graphic
0x08 graphic

W języku obiektowym podstawowym modułem jest klasa. Należy zatem dążyć do tego, aby tylko niektóre zmienne i metody były widoczne na zewnątrz klasy (należały do jej części publicznej). Reszta powinna być ukryta (encapsulated) przed niepowołanym dostępem, czyli zadeklaro­wana jako private lub protected.

Dobrym zwyczajem jest traktowanie wszystkich zmiennych instancyjnych jako prywatnych. Jeżeli któraś z nich ma być dostępna z zewnątrz, to określamy dla niej specjalną metodę dostępu:

class Student extends Osoba {

private int nrIndeksu;

static int liczba = 1;

public int getIndex ( ) {

return nrIndeksu;

}

6.4. Interfejsy

W odróżnieniu od C++, w Javie wszystkie klasy są pochodnymi klasy bazowej Object. Jest to korzeń drzewa hierarchii klas. W drzewie tym obowiązuje pojedyncze dziedziczenie: klasa pochodna może mieć tylko jednego przodka (jedną klasę nadrzędną).

Pozwala to uniknąć dylematów typu "romboidalnego":

0x08 graphic
0x08 graphic

A

B C

D

Czasem jednak dziedziczenie pojedyncze staje się niewygodne: jeżeli klasy C i E mają korzystać z tych samych metod, to musimy umieścić te metody w klasie bazowej A. Powoduje to zbytnie rozrastanie się klas bliskich korzeniowi Object.

Aby temu zaradzić, wprowadzono w Javie wielokrotne dziedziczenie metod. Służy do tego konstrukcja zwana interfejsem:

… // nagłówki metod

}

Wszystkie metody deklarowane w interfejsie są publiczne z definicji. Klasa korzystająca z interfejsu musi podać implementacje wszystkich jego metod:

… // implementacje metod

}

0x08 graphic
0x08 graphic


0x08 graphic
0x08 graphic
0x08 graphic

0x08 graphic
0x08 graphic
0x08 graphic
0x08 graphic
0x08 graphic
0x08 graphic
0x08 graphic


W Javie istnieje tylko jedno drzewo hierarchii klas. Równolegle można definiować drzewa hierarchii interfejsów. Klasa może korzystać z dowolnej liczby interfejsów, lecz musi implementować wszystkie ich metody.


Aplikacja Lektor

interface Kojarzenie {

Lektor kojarz_z ( Student student );

}

public class Lektor extends Osoba implements Kojarzenie {

public static int liczbaLektorów = 0;

public static int liczbaStudEN = 0;

public static int liczbaStudDE = 0;

public static Lektor [ ] lektorzy;

public static Student [ ] studenci;

public static Student [ ] studenciEN;

public static Student [ ] studenciDE;

private String język;

private int nrLektora;

private final static String JESTEM = "Jestem lektor ";

private final static String JĘZYK = ", prowadze jezyk ";

private final static String EN = "angielski";

private final static String DE = "niemiecki";

private final static int MAX_L = 2;

private final static int MAX_S = 4;

// blok inicjowania tablic

static {

lektorzy = new Lektor [ MAX_L ];

lektorzy [0] = new Lektor ( "Bond", EN );

lektorzy [1] = new Lektor ( "Brunner", DE );

studenci = new Student [ MAX_S ];

studenci [0] = new Student ( "Kowalski", EN );

studenci [1] = new Student ( "Cichocki", DE );

studenci [2] = new Student ( "Malinowski", EN );

studenci [3] = new Student ( "Janas", DE );

}

// konstruktory

Lektor ( String nazwisko, String język ) {

super ( NIEZNANE, nazwisko, NIEZNANE );

this.język = język;

nrLektora = liczbaLektorów++;

}

Lektor ( ) {

super ( NIEZNANE, NIEZNANE, NIEZNANE );

this.język = NIEZNANE;

nrLektora = liczbaLektorów++;

}

// prezentacja

void jestem ( ) {

System.out.print ( JESTEM );

if ( imię != NIEZNANE )

System.out.print ( imię + " " );

if ( nazwisko != NIEZNANE )

System.out.print ( nazwisko );

if ( język != NIEZNANE )

System.out.print ( JĘZYK + język );

System.out.println ( MAM + nrLektora );

}

// implementacja metod interfejsu

public Lektor kojarz_z ( Student student ) {

Lektor lektor = null;

for (int i = 0; i < lektorzy.length ; i++) {

if ( lektorzy [ i ].język == student.język )

lektor = lektorzy [ i ];

}

return lektor;

}

// ustalanie liczby studentów studiujących dany język

public static int policz ( String język ) {

int liczba = 0;

for ( int i = 0; i < studenci.length ; i++ )

if ( studenci [ i ].język == język ) liczba++;

return liczba;

}

// tworzenie tablic językowych

private static void wybierz ( Student [ ] studenciEN, Student [ ] studenciDE ) {

Lektor lektor = new Lektor ();

int j_EN = 0, j_DE = 0;

for (int i = 0; i < studenci.length; i++)

{

lektor = lektor.kojarz_z ( studenci [ i ] );

if ( lektor.język == EN )

{

studenciEN [ j_EN ] = studenci [ i ];

j_EN++;

}

else

{

studenciDE [ j_DE ] = studenci [ i ];

j_DE++;

}

}

}

private static void wybierz ( Student [ ] tablica, String język ) {

Lektor lektor = new Lektor ();

int j= 0;

for (int i = 0; i < studenci.length; i++)

{

lektor = lektor.kojarz_z ( studenci [ i ] );

if ( lektor.język == język ) {

tablica [ j ] = studenci [ i ];

j++;

}

}

}

// wyświetlanie wyników

public static void drukuj ( Osoba [ ] osoba ) {

for (int i = 0; i < osoba.length ; i++ )

osoba [ i ].jestem ( );

System.out.println("---------------");

}

// metoda główna

public static void main ( String args [ ] ) {

drukuj ( lektorzy );

drukuj ( studenci );

liczbaStudEN = policz ( EN );

liczbaStudDE = policz ( DE );

studenciEN = new Student [ liczbaStudEN ];

studenciDE = new Student [ liczbaStudDE ];

wybierz ( studenciEN, EN );

wybierz ( studenciDE, DE );

drukuj ( studenciEN );

drukuj ( studenciDE );

}

}

Adam Borkowski Język programowania „Java” 6-1

Adam Borkowski Język programowania „Java” 6-11

Adam Borkowski Język programowania „Java” 6-16

Cichocki

Obiekt B

Obiekt A

Klasa
pochodna 2

Klasa
pochodna 1

Klasa
podstawowa

Kowalski

Lektor

Student

Osoba

Część publiczna

Część
p
ubliczna

Część
prywa
tna

Część
prywatna

Moduł A

Moduł B

Klasa
E

Klasa
C

Klasa
D

Klasa
B

Klasa Object

Interfejs 3

Interfejs 2

Interfejs 1

Klasa
A



Wyszukiwarka

Podobne podstrony:
Java Media FreamWork
java 2
Projekt java
JAVA tablice
Inzynieria oprogramowania w ujeciu obiektowym UML wzorce projektowe i Java iowuje
Java Przewodnik dla poczatkujacych Wydanie V javpp5
zasady grupy, java, javascript, oprogramowanie biurowe, programowanie, programowanie 2, UTK, systemy
praktyczny kurs java NX2M5DXARLEHY6NHXOS5FJHKLI6ACRLQQSDRS2Q
notatki java 08
Praktyczny kurs Java
Java praca domowa 10
java 3 id 226367 Nieznany
Java Coding rules
java object serialization speci Nieznany
java script TY2DWI33KJCAKQBCFPFEFQ736KLTSQZ3F6JQE2Q
JP SS 4 start Java
notatki java 05
java swing
notatki java 07
helion java cwiczenia zaawansow Nieznany

więcej podobnych podstron