Transcript INTERFEJSY I KLASY WEWNĘTRZNE
Slide 1
INTERFEJSY
I
KLASY WEWNĘTRZNE
Artur Szwabowicz 140907
Slide 2
Interfejs
Interfejs jest to spolszczenie angielskiego słowa interface, które na polski bywa
tłumaczone jako styk.
•
•
•
interfejs klasy - w językach obiektowych abstrakcyjna reprezentacja klasy
pozwalająca na wykorzystywanie jej bez odwoływania się do konkretnej
implementacji,
interfejs (urządzenie) - urządzenie elektroniczne lub optyczne pozwalające na
komunikację między dwoma innymi urządzeniami, których bezpośrednio nie da się ze
sobą połączyć,
interfejs użytkownika - oprogramowanie pozwalające na interakcję między
aplikacjami i użytkownikiem:
o interfejs graficzny - interfejs użytkownika komunikujący stan programu w
postaci graficznej na ekranie (lub wyświetlaczu), który jako wejście
wykorzystuje urządzenie wskazujące (myszkę, touchpad, tablet, joystick, itp.) i
klawiaturę,
o interfejs tekstowy - interfejs użytkownika komunikujący stan aplikacji w postaci
znaków na ekranie (lub wyświetlaczu), wykorzystujący jako wejście z reguły
tylko klawiaturę.
Slide 3
Interfejs
Słowo kluczowe interface
Interfejsy Javy rozwiązują problem wielokrotnego
dziedziczenia, gdyż zapewniają znaczną część korzyści,
jakie w przypadku wielokrotnego dziedziczenia daje
możliwość wykorzystania polimorfizmu, a jednocześnie
chroni nas przed problemem „śmiertelnego rombu” –
wymuszają by wszystkie metody były abstrakcyjne!
Klasa potomna musi zaimplementować wszystkie metody
(wszystkie metody abstrakcyjne muszą zostać
zaimplementowane w pierwszej konkretnej klasie
potomnej).
Interfejs informuje: „Oto jak będą wyglądać wszystkie
klasy implementujące mnie.”
Slide 4
Obie klasy –
NagrywarkaCD oraz
NagrywarkaDVD
dziedziczą po klasie
NagrywarkaCyfrowa i
obie przesłaniają metodę
zapisz().
Obie dziedziczą
a Rozwiązania
wykorzystujące
także składową i typu int.
Interfejs
„dwie klasy bazowe” przysparzają tylko jednego
problemu...
Nosi ono nazwę „wielokrotnego dziedziczenia” i może być naprawdę
niebezpieczne.
To znaczy – mogłoby być – gdyby tylko można je było wykorzystać w Javie.
Jednak nie jest,
powstania
Oto problem, jakiego
przysparza wielokrotne
dziedziczenie. Która z
gdyż wielokrotne dziedziczeniemetod
możezapisz()
doprowadzić
zostanie
wywołana
w przypadku
problemu nazywanego „śmiertelnym
rombem”.
wywołania tej metody dla
obiektu NapedCombo?
do
Slide 5
Interfejs
W drzewie dziedziczenie
zwierząt, klasy Zwierze,
Psowate i Kotowate
zdefiniowano jako klasy
abstrakcyjne, a „liście”
tego drzewa są klasami
konkretnymi.
Ale, co zrobić aby klasy
Pies i Kot mogły
wykonywać czynności
charakterystyczne dla klasy
ZwierzakDomowy.
Slide 6
Interfejs
Można umieścić
wszystkie metody
klasy
ZwierzakDomowy w
klasie Zwierze
Slide 7
Interfejs
Można umieścić
wszystkie metody klasy
ZwierzakDomowy w
klasie Zwierze, lecz
zadeklarować je jako
metody abstrakcyjne.
Slide 8
Interfejs
Można umieścić metody
charakterystyczne dla
zwierzaków domowych
wyłącznie w klasach, w
jakich powinny się
znaleźć.
Slide 9
Interfejs
Na pomoc
spieszą
interfejsy.
Wygląda na to, że na
samej górze hierarchii
dziedziczenia
potrzebujemy DWÓCH
klas.
Slide 10
Interfejs
Na pomoc
spieszą
interfejsy.
Slide 11
Interfejs
Interfejs przypomina całkowicie abstrakcyjną
klasę.
Zamiast
słowa
kluczowego „class”
należy użyć słowa
„interface”.
Wszytkie metody wchodzące w
Aby ZDEFINIOWAĆ interfejs:
skłąd interfejsu są abstrakcyjne,
zatem wszystkie klasy, które
public interface
ZwierzakDomowy
{...}
spełniają
relację JEST z
interfejsem, MUSZĄ te metody
implementować (czyli
przesłaniać).
Aby ZAIMPLEMENTOWAĆ interfejs:
public class Pies extends Psowate implements ZwierzakDomowy
{...}
Slide 12
Interfejs
public interface ZwierzakDomowy {
public abstract void badzMilutki();
public abstract void bawSie();
}
Skoro chce być
zwierzakiem
domowym, zatem
musi
zaimplementować
metody tworzące
interfejs
ZwierzakDomowy.
public class Pies extends Psowate implements
ZwierzakDomowy {
public void badzMilutki() {...}
public void bawSie() {...}
public void wedruj() {...}
public void jedz() {...}
}
A to są zwyczajnie
przysłaniane metody
klasy Zwierze.
Slide 13
Interfejs
Ten sam interfejs
mogą
implementować
klasy pochodzące z
różnych drzew
dziedziczenia.
Slide 14
Interfejs
Każde pole umieszczone w interfejsie staje się automatycznie statyczne i finalne.
// Użycie interfejsów do grupowania stałych.
public interface Miesiace {
int
JANUARY = 1, FEBRUARY = 2, MARCH = 3,
APRIL = 4, MAY = 5, JUNE = 6, JULY = 7,
AUGUST = 8, SEPTEMBER = 9, OCTOBER = 10,
NOVEMBER = 11, DECEMBER = 12;
}
Wyrażenie Miesiace.MAY zwróci wartość typu int równą 5.
W Javie przyjęto zwyczaj stosowania wyłącznie wielkich liter w nazwach pól typu static
final, posiadających stałe wartości inicjalizujące.
Slide 15
Interfejs
Klasa może implementować więcej niż jeden interfejs. Wszystkie
nazwy interfejsów umieszczamy po słowie implements i rozdzielamy
przecinkami.
W następnym przykładzie pokazano, iż:
–
–
można połączyć klasę konkretną z kilkoma interfejsami w celu stworzenia
nowej klasy
po interfejsach można dziedziczyć – otrzymujemy wtedy kolejny interfejs
Slide 16
Obiekt Hero może być
przekazywany do
wszystkich tych
metod, co oznacza, że
możliwe jest
rzutowanie na każdy z
// Wiele
interfejsów.
interfejsów.
interface CanFight {
void fight();
}
interface CanSwim {
void swim();
}
interface CanFly {
void fly();
}
class ActionCharacter {
public void fight() { }
}
Interfejs
W klasie
Klasa
HeroAdventure
dziedziczy
cztery
po występują
ActionCharacter,
metody
pobierające
dlatego
nie
jako argumenty
różne
implementuje
metody
interfejsy
oraz klasę
fight().
konkretną
class Hero extends ActionCharacter
implements CanFight, CanSwim, CanFly {
public void swim() { }
public void fly() { }
}
public class Adventure {
public static void t(CanFight x) { x.fight(); }
public static void u(CanSwim x) { x.swim(); }
public static void v(CanFly x) { x.fly(); }
public static void w(ActionCharacter x) {
x.fight(); }
public static void main(String[] args) {
Hero h = new Hero();
t(h); // Obiekt Hero jako CanFight
u(h); // Obiekt Hero jako CanSwim
v(h); // Obiekt Hero jako CanFly
w(h); // Obiekt Hero jako ActionCharacter
}
}
Slide 17
Interfejs
Po co są interfejsy?
Dają nam możliwość rzutowania na kilka typów bazowych.
Uniemożliwiają programiście tworzenie obiektów naszej klasy.
Slide 18
Interfejs
Kiedy powinniśmy stosować interfejsy a kiedy klasy abstrakcyjne?
Interfejs daje nam korzyści zapewniane przez abstrakcyjność klas oraz
dodatkowe – wynikające z bycia interfejsem.
Jeżeli możliwe jest stworzenie klasy bazowej bez definiowania żadnych metod
lub zmiennych składowych, powinniśmy zawsze wybierać interfejsy, a nie klasy
abstrakcyjne.
Slide 19
Klasy wewnętrzne
Możliwe jest umieszczenie definicji klasy wewnątrz innej definicji klasy.
Klasy wewnętrzne umożliwiają grupowanie logicznie powiązanych ze sobą
klas i kontrolowanie widoczności jednych w drugich.
Slide 20
Klasy wewnętrzne
Aby utworzyć klasę wewnętrzną, należy upewnić się, że definicja klasy
wewnętrznej znajduje się wewnątrz nawiasów klamrowych klasy
zewnętrznej.
class MojaKlasaZewnetrzna
{
class MojaKlasaWewnetrzna
{
void doDziela() {...}
}
}
Slide 21
Klasy wewnętrzne
Klasa wewnętrzna może używać wszystkich składowych i metod klasy
zewnętrznej, nawet tych prywatnych.
Klasa wewnętrzna może się posługiwać składowymi i metodami klasy
zewnętrznej jak gdyby były zadeklarowane w niej samej.
Slide 22
Klasy wewnętrzne
Obiekt klasy wewnętrznej musi być związany z konkretnym obiektem klasy zewnętrznej
przechowywanym na stercie.
Obiekt wewnętrzny oraz zewnętrzny są ze sobą powiązane w szczególny sposób.
1.
2.
3.
Utwórz obiekt klasy zewnętrznej.
Te dwa obiekty
Utwórz obiekt klasy wewnętrznej używając przy tym
obiektu klasy
przebywające
na
zewnętrznej.
stercie łączy
szczególna więź.
Teraz obiekt klasy zewnętrznej oraz obiekt klasy wewnętrznej są ze sobą
połączone w szczególny sposób.
Obiekt wewnętrzny
może korzystać ze
składowych obiektu
zewnętrznego (i na
odwrót).
Slide 23
Klasy wewnętrzne
class MojaKlasaZewnetrzna
{
}
Klasa zewnętrzna ma
Klasa zewnętrzna ma
składową
prywatną oobiektu
Utworzenie
składową
prywatną o
nazwie
„x”
klasy
wewnętrznej
nazwie „x”
private int x;
MojaKlasaWewnetrzna wew = new MojaKlasaWewnetrzna();
public void zrobCos()
Wywołanie metody
{
klasy wewnętrznej
wew.doRoboty();
}
class MojaKlasaWewnetrzna
{
void doRoboty()
{
x = 42;
Metoda klasy
}
wewnętrznej używa
}
składowej „x” klasy
zewnętrznej
Slide 24
Klasy wewnętrzne
Istnieje możliwość utworzenia obiektu klasy wewnętrznej z poziomu kodu
działającego poza klasą zewnętrzną, jednak należy w tym celu użyć
specjalnej składni.
class Tmp
{
public static void main(String[] args)
{
KlasaZewnetrzna objZew = new KlasaZewnetrzna();
KlasaZewnetrzna.KlasaWewnetrzna objWew = objZew.new
KlasaWewnetrzna();
}
}
Slide 25
Klasy wewnętrzne
Nasze programy mogą zawierać:
1.
2.
3.
4.
5.
6.
Klasę zdefiniowaną wewnątrz metody.
Klasę zdefiniowaną wewnątrz zasięgu określonego w metodzie.
Anonimową klasę implementującą interfejs.
Anonimową klasę rozszerzającą klasę posiadającą konstruktor inny
od domyślnego.
Anonimową klasę przeprowadzającą inicjalizację pól.
Anonimową klasę przeprowadzającą konstrukcje zawierającą
inicjalizacje instancji (anonimowe klasy wewnętrzne nie mogą mieć
konstruktorów).
Slide 26
Klasy wewnętrzne
Co sprawia, że klasy wewnętrzne są ważne?
Dają nam możliwość kilkukrotnego zaimplementowania tego samego
interfejsu w jednej klasie.
Należy pamiętać, ze w normalnej klasie Javy nie można
zaimplementować metody więcej niż jeden raz. Jednak stosując
klasy wewnętrzne, każda z nich może implementować ten sam
interfejs, dzięki czemu można stworzyć różne implementacje tej
samej metody interfejsu.
Slide 27
Interfejsy i klasy wewnętrzne
Dziękuję za uwagę
Artur Szwabowicz
INTERFEJSY
I
KLASY WEWNĘTRZNE
Artur Szwabowicz 140907
Slide 2
Interfejs
Interfejs jest to spolszczenie angielskiego słowa interface, które na polski bywa
tłumaczone jako styk.
•
•
•
interfejs klasy - w językach obiektowych abstrakcyjna reprezentacja klasy
pozwalająca na wykorzystywanie jej bez odwoływania się do konkretnej
implementacji,
interfejs (urządzenie) - urządzenie elektroniczne lub optyczne pozwalające na
komunikację między dwoma innymi urządzeniami, których bezpośrednio nie da się ze
sobą połączyć,
interfejs użytkownika - oprogramowanie pozwalające na interakcję między
aplikacjami i użytkownikiem:
o interfejs graficzny - interfejs użytkownika komunikujący stan programu w
postaci graficznej na ekranie (lub wyświetlaczu), który jako wejście
wykorzystuje urządzenie wskazujące (myszkę, touchpad, tablet, joystick, itp.) i
klawiaturę,
o interfejs tekstowy - interfejs użytkownika komunikujący stan aplikacji w postaci
znaków na ekranie (lub wyświetlaczu), wykorzystujący jako wejście z reguły
tylko klawiaturę.
Slide 3
Interfejs
Słowo kluczowe interface
Interfejsy Javy rozwiązują problem wielokrotnego
dziedziczenia, gdyż zapewniają znaczną część korzyści,
jakie w przypadku wielokrotnego dziedziczenia daje
możliwość wykorzystania polimorfizmu, a jednocześnie
chroni nas przed problemem „śmiertelnego rombu” –
wymuszają by wszystkie metody były abstrakcyjne!
Klasa potomna musi zaimplementować wszystkie metody
(wszystkie metody abstrakcyjne muszą zostać
zaimplementowane w pierwszej konkretnej klasie
potomnej).
Interfejs informuje: „Oto jak będą wyglądać wszystkie
klasy implementujące mnie.”
Slide 4
Obie klasy –
NagrywarkaCD oraz
NagrywarkaDVD
dziedziczą po klasie
NagrywarkaCyfrowa i
obie przesłaniają metodę
zapisz().
Obie dziedziczą
a Rozwiązania
wykorzystujące
także składową i typu int.
Interfejs
„dwie klasy bazowe” przysparzają tylko jednego
problemu...
Nosi ono nazwę „wielokrotnego dziedziczenia” i może być naprawdę
niebezpieczne.
To znaczy – mogłoby być – gdyby tylko można je było wykorzystać w Javie.
Jednak nie jest,
powstania
Oto problem, jakiego
przysparza wielokrotne
dziedziczenie. Która z
gdyż wielokrotne dziedziczeniemetod
możezapisz()
doprowadzić
zostanie
wywołana
w przypadku
problemu nazywanego „śmiertelnym
rombem”.
wywołania tej metody dla
obiektu NapedCombo?
do
Slide 5
Interfejs
W drzewie dziedziczenie
zwierząt, klasy Zwierze,
Psowate i Kotowate
zdefiniowano jako klasy
abstrakcyjne, a „liście”
tego drzewa są klasami
konkretnymi.
Ale, co zrobić aby klasy
Pies i Kot mogły
wykonywać czynności
charakterystyczne dla klasy
ZwierzakDomowy.
Slide 6
Interfejs
Można umieścić
wszystkie metody
klasy
ZwierzakDomowy w
klasie Zwierze
Slide 7
Interfejs
Można umieścić
wszystkie metody klasy
ZwierzakDomowy w
klasie Zwierze, lecz
zadeklarować je jako
metody abstrakcyjne.
Slide 8
Interfejs
Można umieścić metody
charakterystyczne dla
zwierzaków domowych
wyłącznie w klasach, w
jakich powinny się
znaleźć.
Slide 9
Interfejs
Na pomoc
spieszą
interfejsy.
Wygląda na to, że na
samej górze hierarchii
dziedziczenia
potrzebujemy DWÓCH
klas.
Slide 10
Interfejs
Na pomoc
spieszą
interfejsy.
Slide 11
Interfejs
Interfejs przypomina całkowicie abstrakcyjną
klasę.
Zamiast
słowa
kluczowego „class”
należy użyć słowa
„interface”.
Wszytkie metody wchodzące w
Aby ZDEFINIOWAĆ interfejs:
skłąd interfejsu są abstrakcyjne,
zatem wszystkie klasy, które
public interface
ZwierzakDomowy
{...}
spełniają
relację JEST z
interfejsem, MUSZĄ te metody
implementować (czyli
przesłaniać).
Aby ZAIMPLEMENTOWAĆ interfejs:
public class Pies extends Psowate implements ZwierzakDomowy
{...}
Slide 12
Interfejs
public interface ZwierzakDomowy {
public abstract void badzMilutki();
public abstract void bawSie();
}
Skoro chce być
zwierzakiem
domowym, zatem
musi
zaimplementować
metody tworzące
interfejs
ZwierzakDomowy.
public class Pies extends Psowate implements
ZwierzakDomowy {
public void badzMilutki() {...}
public void bawSie() {...}
public void wedruj() {...}
public void jedz() {...}
}
A to są zwyczajnie
przysłaniane metody
klasy Zwierze.
Slide 13
Interfejs
Ten sam interfejs
mogą
implementować
klasy pochodzące z
różnych drzew
dziedziczenia.
Slide 14
Interfejs
Każde pole umieszczone w interfejsie staje się automatycznie statyczne i finalne.
// Użycie interfejsów do grupowania stałych.
public interface Miesiace {
int
JANUARY = 1, FEBRUARY = 2, MARCH = 3,
APRIL = 4, MAY = 5, JUNE = 6, JULY = 7,
AUGUST = 8, SEPTEMBER = 9, OCTOBER = 10,
NOVEMBER = 11, DECEMBER = 12;
}
Wyrażenie Miesiace.MAY zwróci wartość typu int równą 5.
W Javie przyjęto zwyczaj stosowania wyłącznie wielkich liter w nazwach pól typu static
final, posiadających stałe wartości inicjalizujące.
Slide 15
Interfejs
Klasa może implementować więcej niż jeden interfejs. Wszystkie
nazwy interfejsów umieszczamy po słowie implements i rozdzielamy
przecinkami.
W następnym przykładzie pokazano, iż:
–
–
można połączyć klasę konkretną z kilkoma interfejsami w celu stworzenia
nowej klasy
po interfejsach można dziedziczyć – otrzymujemy wtedy kolejny interfejs
Slide 16
Obiekt Hero może być
przekazywany do
wszystkich tych
metod, co oznacza, że
możliwe jest
rzutowanie na każdy z
// Wiele
interfejsów.
interfejsów.
interface CanFight {
void fight();
}
interface CanSwim {
void swim();
}
interface CanFly {
void fly();
}
class ActionCharacter {
public void fight() { }
}
Interfejs
W klasie
Klasa
HeroAdventure
dziedziczy
cztery
po występują
ActionCharacter,
metody
pobierające
dlatego
nie
jako argumenty
różne
implementuje
metody
interfejsy
oraz klasę
fight().
konkretną
class Hero extends ActionCharacter
implements CanFight, CanSwim, CanFly {
public void swim() { }
public void fly() { }
}
public class Adventure {
public static void t(CanFight x) { x.fight(); }
public static void u(CanSwim x) { x.swim(); }
public static void v(CanFly x) { x.fly(); }
public static void w(ActionCharacter x) {
x.fight(); }
public static void main(String[] args) {
Hero h = new Hero();
t(h); // Obiekt Hero jako CanFight
u(h); // Obiekt Hero jako CanSwim
v(h); // Obiekt Hero jako CanFly
w(h); // Obiekt Hero jako ActionCharacter
}
}
Slide 17
Interfejs
Po co są interfejsy?
Dają nam możliwość rzutowania na kilka typów bazowych.
Uniemożliwiają programiście tworzenie obiektów naszej klasy.
Slide 18
Interfejs
Kiedy powinniśmy stosować interfejsy a kiedy klasy abstrakcyjne?
Interfejs daje nam korzyści zapewniane przez abstrakcyjność klas oraz
dodatkowe – wynikające z bycia interfejsem.
Jeżeli możliwe jest stworzenie klasy bazowej bez definiowania żadnych metod
lub zmiennych składowych, powinniśmy zawsze wybierać interfejsy, a nie klasy
abstrakcyjne.
Slide 19
Klasy wewnętrzne
Możliwe jest umieszczenie definicji klasy wewnątrz innej definicji klasy.
Klasy wewnętrzne umożliwiają grupowanie logicznie powiązanych ze sobą
klas i kontrolowanie widoczności jednych w drugich.
Slide 20
Klasy wewnętrzne
Aby utworzyć klasę wewnętrzną, należy upewnić się, że definicja klasy
wewnętrznej znajduje się wewnątrz nawiasów klamrowych klasy
zewnętrznej.
class MojaKlasaZewnetrzna
{
class MojaKlasaWewnetrzna
{
void doDziela() {...}
}
}
Slide 21
Klasy wewnętrzne
Klasa wewnętrzna może używać wszystkich składowych i metod klasy
zewnętrznej, nawet tych prywatnych.
Klasa wewnętrzna może się posługiwać składowymi i metodami klasy
zewnętrznej jak gdyby były zadeklarowane w niej samej.
Slide 22
Klasy wewnętrzne
Obiekt klasy wewnętrznej musi być związany z konkretnym obiektem klasy zewnętrznej
przechowywanym na stercie.
Obiekt wewnętrzny oraz zewnętrzny są ze sobą powiązane w szczególny sposób.
1.
2.
3.
Utwórz obiekt klasy zewnętrznej.
Te dwa obiekty
Utwórz obiekt klasy wewnętrznej używając przy tym
obiektu klasy
przebywające
na
zewnętrznej.
stercie łączy
szczególna więź.
Teraz obiekt klasy zewnętrznej oraz obiekt klasy wewnętrznej są ze sobą
połączone w szczególny sposób.
Obiekt wewnętrzny
może korzystać ze
składowych obiektu
zewnętrznego (i na
odwrót).
Slide 23
Klasy wewnętrzne
class MojaKlasaZewnetrzna
{
}
Klasa zewnętrzna ma
Klasa zewnętrzna ma
składową
prywatną oobiektu
Utworzenie
składową
prywatną o
nazwie
„x”
klasy
wewnętrznej
nazwie „x”
private int x;
MojaKlasaWewnetrzna wew = new MojaKlasaWewnetrzna();
public void zrobCos()
Wywołanie metody
{
klasy wewnętrznej
wew.doRoboty();
}
class MojaKlasaWewnetrzna
{
void doRoboty()
{
x = 42;
Metoda klasy
}
wewnętrznej używa
}
składowej „x” klasy
zewnętrznej
Slide 24
Klasy wewnętrzne
Istnieje możliwość utworzenia obiektu klasy wewnętrznej z poziomu kodu
działającego poza klasą zewnętrzną, jednak należy w tym celu użyć
specjalnej składni.
class Tmp
{
public static void main(String[] args)
{
KlasaZewnetrzna objZew = new KlasaZewnetrzna();
KlasaZewnetrzna.KlasaWewnetrzna objWew = objZew.new
KlasaWewnetrzna();
}
}
Slide 25
Klasy wewnętrzne
Nasze programy mogą zawierać:
1.
2.
3.
4.
5.
6.
Klasę zdefiniowaną wewnątrz metody.
Klasę zdefiniowaną wewnątrz zasięgu określonego w metodzie.
Anonimową klasę implementującą interfejs.
Anonimową klasę rozszerzającą klasę posiadającą konstruktor inny
od domyślnego.
Anonimową klasę przeprowadzającą inicjalizację pól.
Anonimową klasę przeprowadzającą konstrukcje zawierającą
inicjalizacje instancji (anonimowe klasy wewnętrzne nie mogą mieć
konstruktorów).
Slide 26
Klasy wewnętrzne
Co sprawia, że klasy wewnętrzne są ważne?
Dają nam możliwość kilkukrotnego zaimplementowania tego samego
interfejsu w jednej klasie.
Należy pamiętać, ze w normalnej klasie Javy nie można
zaimplementować metody więcej niż jeden raz. Jednak stosując
klasy wewnętrzne, każda z nich może implementować ten sam
interfejs, dzięki czemu można stworzyć różne implementacje tej
samej metody interfejsu.
Slide 27
Interfejsy i klasy wewnętrzne
Dziękuję za uwagę
Artur Szwabowicz