13 kwietnia 2008

SCJP - Związki typu IS-A oraz HAS-A

Niniejszym rozpoczynam streszczenie drugiego rozdziału książki "SCJP Sun Certified Programmer for Java 5 Study Guide (Exam 310-055)" – kontynuuję dzieło zapowiedziane w artykule "Przygotowania do SCJP czas zacząć". Rozdział drugi ma inną naturę niż pierwszy – więcej tu rozważań o stylu a mniej konkretów – dlatego do zadania podejdę nieco inaczej. Nie będzie już opracowań krok po kroku, sekcja za sekcją, bo też nie czuje żeby to było celowe i potrzebne. W zamian pojawią się artykuły, w których na wyrywki przedstawię główne zagadnienia. Powiem wprost – autorzy w rozdziale drugim zwyczajnie przynudzają. Nie to żebym krytykował Książkę, po prostu, jest ona dedykowana dla osób początkujących, które jeszcze nie pewnie posługują się językiem Java i nie do końca rozumieją zagadnienia programowania obiektowego. Zdecydowałem się na częściowo anglojęzyczny tytuł dzisiejszego artykułu, ponieważ zasadniczym jego celem jest wytłumaczenie znaczenia właśnie tych anglojęzycznych terminów, tj. co to znaczy, że klasy są w związku (ang. relationship) IS-A albo HAS-A.

IS-A oznacza "jest". Warzywo jest rośliną, marchewka jest warzywem, ale rośliną również. Oprócz tego warzywo jest jadalne, ale roślina już nie koniecznie. O czym ja tu piszę? Naturalnie, o Javie i egzaminie SCJP. Rozważmy następujące klasy i interfejsy:


class Plant { }

interface Eatable {}

class Vegetable extends Plant implements Eatable { }
// Vegetable IS-A Plant, Vegetable IS-A Eatable

class Carrot extends Vegetable { }
// Carrot IS-A Vegetable, Carrot IS-A Eatable, Carrot IS-A Plant

Związki IS-A są oparte na dziedziczeniu i implementacji interfejsów. Klasa A jest w relacji IS-A z klasą B, jeśli A jest klasą pochodną – bezpośrednio lub pośrednio – klasy B, ewentualnie klasa A IS-A B jeśli B jest interfejsem i A implementuje B. Mówiąc jeszcze inaczej, A IS-A B, jeśli wyrażenie ‘(new A()) instanceof B’ ma wartość ‘true’.

HAS-A oznacza "ma". Firma ma szefa, który jest pracownikiem. Jeśli chcemy czegoś od firmy, np. podwyżki to niby uruchamiamy procedury w firmie, ale decyzję podejmuje jednak szef, firma deleguje tego typu zadania właśnie szefom. W języku Javy wygląda to tak:


class Company {
private Boss boss; // Company HAS-A Boss

int requestPayRise(Employee emp, int amount) {
return boss.requestPayRise(emp, amount);
}
}

class Boss extends Employee { // Boss IS-A Employee
int requestPayRise(Employee emp, int amount) {
if(emp instanceof Boss) {
return amount;
} else {
return 0;
}
}
}

class Employee {
private Company company; // Employee HAS-A Company

private int salary;

void requestPayRise(int amount) {
salary += company.requestPayRise(this, amount);
}
}

Związek HAS-A oparty jest na kompozycji. Klasa A jest w relacji HAS-A z klasą B, tj. A HAS-A B, jeśli klasa A posiada referencję do obiektów klasy B. Z relacjami typu HAS-A związany jest kolejny ważny aspekt – delegacja odpowiedzialności. W powyższym przykładzie klasa Company posiada metodę requestPayRise(), jednak jest ona w całości oddelegowana do powiązanego obiektu klasy Boss. To, jaki jest rezultat działania metody requestPayRise() w klasie Company zależy więc w pełni od implementacji w klasie Boss.

2 komentarze:

Jacek Laskowski pisze...

Muszę przyznać, że obawiałem się długości materiału (wcześniej nie spojrzałem jaki faktycznie jest obszerny), ale kiedy zacząłem czytać, wciągnął mnie i czytałem wytrwale z wielkim zainteresowaniem, aż...nastąpił koniec. Tylko tyle?! Nie może być. Chcę więcej! Krótko i na temat. Piszesz bardzo ciekawie i planuję podkraść trochę tego stylu do swojej twórczości literackiej. To na pewno będzie miało swoje reperkusje na poziom wiedzy o Javie w Polsce i sposób jej prezentowania szerszemu gronu! Z niecierpliwością oczekuję kolejnych wpisów. W zasadzie ja ich oczekuję - teraz i zaraz! :P

Jacek

Mariusz Lipiński pisze...

Taka nobilitacja od takiej persony... nie wierzę własnym oczom! :) Będzie więcej Jacek, będzie i cieszę się, że się podoba.

Pozdrawiam