Podstawy programowania obiektowego

Podobne dokumenty
Kurs programowania. Wykład 2. Wojciech Macyna. 17 marca 2016

Java - tablice, konstruktory, dziedziczenie i hermetyzacja

Dziedziczenie. dr Jarosław Skaruz

Programowanie obiektowe i zdarzeniowe

Polimorfizm. dr Jarosław Skaruz

Technologie i usługi internetowe cz. 2

Wykład 6: Dziedziczenie

Programowanie w Javie 1 Wykład i Ćwiczenia 3 Programowanie obiektowe w Javie cd. Płock, 16 października 2013 r.

Programowanie obiektowe Wykład 6. Dariusz Wardowski. dr Dariusz Wardowski, Katedra Analizy Nieliniowej, WMiI UŁ 1/14

Informatyka I. Dziedziczenie. Nadpisanie metod. Klasy abstrakcyjne. Wskaźnik this. Metody i pola statyczne. dr inż. Andrzej Czerepicki

Java: kilka brakujących szczegółów i uniwersalna nadklasa Object

Klasa jest nowym typem danych zdefiniowanym przez użytkownika. Najprostsza klasa jest po prostu strukturą, np

Programowanie obiektowe w języku

Dziedziczenie. Tomasz Borzyszkowski

Enkapsulacja, dziedziczenie, polimorfizm

Programowanie 2. Język C++. Wykład 3.

TEMAT : KLASY DZIEDZICZENIE

C++ - dziedziczenie. C++ - dziedziczenie. C++ - dziedziczenie. C++ - dziedziczenie. C++ - dziedziczenie C++ - DZIEDZICZENIE.

Zaawansowane programowanie w C++ (PCP)

Wykład V. Programowanie II - semestr II Kierunek Informatyka. dr inż. Janusz Słupik. Wydział Matematyki Stosowanej Politechniki Śląskiej

Polimorfizm, metody wirtualne i klasy abstrakcyjne

Klasy abstrakcyjne, interfejsy i polimorfizm

JAVA W SUPER EXPRESOWEJ PIGUŁCE

2. Klasy cz. 2 - Konstruktor kopiujący. Pola tworzone statycznie i dynamicznie - Funkcje zaprzyjaźnione - Składowe statyczne

Dziedziczenie jednobazowe, poliformizm

Programowanie obiektowe - 1.

Dokumentacja do API Javy.

Programowanie współbieżne Wykład 8 Podstawy programowania obiektowego. Iwona Kochaoska

DOSTĘP DO METOD I ZMIENNYCH. Dostęp do zmiennych (na podstawie:l.lemay,r.cadenhead,java 2 dla każdego, Helion 2001)

Języki i techniki programowania Ćwiczenia 3 Dziedziczenie

PARADYGMATY PROGRAMOWANIA Wykład 4

Zaawansowane programowanie w języku C++ Programowanie obiektowe

Programowanie obiektowe

Składnia C++ Programowanie Obiektowe Mateusz Cicheński

Kurs programowania. Wykład 1. Wojciech Macyna. 3 marca 2016

Dziedziczenie. Streszczenie Celem wykładu jest omówienie tematyki dziedziczenia klas. Czas wykładu 45 minut.

Wykład 9: Polimorfizm i klasy wirtualne

Klasa dziedzicząca posiada wszystkie cechy klasy bazowej (plus swoje własne) dodawanie nowego kodu bez edycji (i ewentualnego wprowadzania

1. Które składowe klasa posiada zawsze, niezależnie od tego czy je zdefiniujemy, czy nie?

.NET Klasy, obiekty. ciąg dalszy

C++ - polimorfizm. C++ - polimorfizm. C++ - polimorfizm. C++ - polimorfizm. C++ - polimorfizm POLIMORFIZM

Języki Programowania. Prowadząca: dr inż. Hanna Zbroszczyk. tel: Konsultacje: piątek:

Interfejsy. Programowanie obiektowe. Paweł Rogaliński Instytut Informatyki, Automatyki i Robotyki Politechniki Wrocławskiej

Kurs WWW. Paweł Rajba.

Klasy abstrakcyjne i interfejsy

Język JAVA podstawy. Wykład 4, część 1. Jacek Rumiński. Politechnika Gdańska, Inżynieria Biomedyczna

Podstawy Języka Java

Związek między pojęciami Zasada podstawialności Podklasy muszą realizować kontrakt zawarty przez nadklasy

Wykład 5 Okna MDI i SDI, dziedziczenie

Wprowadzenie do programowanie obiektowego w języku C++

C++ - dziedziczenie. C++ - dziedziczenie. C++ - dziedziczenie. C++ - dziedziczenie. C++ - dziedziczenie C++ - DZIEDZICZENIE.

Programowanie obiektowe

Zaawansowane programowanie w C++ (PCP)

Aplikacje Internetowe. Najprostsza aplikacja. Komponenty Javy. Podstawy języka Java

Interfejsy i klasy wewnętrzne

DOSTĘP DO METOD I ZMIENNYCH, TABLICE. Dostęp do zmiennych (na podstawie:l.lemay,r.cadenhead,java 2 dla kaŝdego, Helion 2001)

Projektowanie obiektowe. Roman Simiński Polimorfizm

Kurs programowania. Wykład 13. Wojciech Macyna. 14 czerwiec 2017

Wstęp do programowania obiektowego. WYKŁAD 3 Dziedziczenie Pola i funkcje statyczne Funkcje zaprzyjaźnione, this

Definiowanie własnych klas

Informatyka I. Klasy i obiekty. Podstawy programowania obiektowego. dr inż. Andrzej Czerepicki. Politechnika Warszawska Wydział Transportu 2018

Kurs programowania. Wstęp - wykład 0. Wojciech Macyna. 22 lutego 2016

Wykład 7: Pakiety i Interfejsy

Programowanie obiektowe

Programowanie obiektowe

Mechanizm dziedziczenia

Składnia C++ Programowanie Obiektowe Mateusz Cicheński

Podstawy Programowania Obiektowego

Java. język programowania obiektowego. Programowanie w językach wysokiego poziomu. mgr inż. Anna Wawszczak

TEMAT : KLASY POLIMORFIZM

Materiały do zajęć VII

Wykład 4: Klasy i Metody

Obiekt klasy jest definiowany poprzez jej składniki. Składnikami są różne zmienne oraz funkcje. Składniki opisują rzeczywisty stan obiektu.

Dziedziczenie i interfejsy

UML a kod w C++ i Javie. Przypadki użycia. Diagramy klas. Klasy użytkowników i wykorzystywane funkcje. Związki pomiędzy przypadkami.

Platformy Programistyczne Podstawy języka Java

Programowanie obiektowe

Programowanie w Javie - wykład 3

Programowanie Obiektowe i C++

Programowanie obiektowe, wykład nr 6. Klasy i obiekty

Abstrakcyjny typ danych

Aplikacje w środowisku Java

Wykład 02. Programowanie obiektowe. Maciej Wołoszyn 10 marca Spis treści.

Czym jest polimorfizm?

Marcin Luckner Politechnika Warszawska Wydział Matematyki i Nauk Informacyjnych

Języki i metody programowania Java Lab2 podejście obiektowe

Java Język programowania

Obszar statyczny dane dostępne w dowolnym momencie podczas pracy programu (wprowadzone słowem kluczowym static),

Programowanie urządzeń mobilnych

C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy. Metody stałe w klasie

Programowanie w Javie wykład 7 Klasy c.d. (przeciążanie metod, polimorfizm) Metody i klasy abstrakcyjne Bloki inicjalizacyjne

Programowanie w Internecie. Java

Podstawy Programowania semestr drugi. Wykład czternasty

C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy. C++ - klasy INNE SPOSOBY INICJALIZACJI SKŁADOWYCH OBIEKTU

Wykład 9: Metody wirtualne i polimorfizm

Podstawy programowania obiektowego

Podstawy programowania obiektowego

PARADYGMATY PROGRAMOWANIA Wykład 2

Typy klasowe (klasy) 1. Programowanie obiektowe. 2. Założenia paradygmatu obiektowego:

Transkrypt:

Podstawy programowania obiektowego Technologie internetowe Wykład 7

Program wykładu Dziedziczenie Wywołania konstruktorów w dziedziczeniu Hermetyzacja w dziedziczeniu Dziedziczenie typu, rzutowanie w górę i w dół Mechanizm RTTI Nadpisywanie pól Nadpisywanie metod polimorfizm Klasy i metody finalne Klasy i metody abstrakcyjne

Dziedziczenie technika konstruowania nowych klas z wykorzystaniem klas już istniejących (jak kompozycja!) opisuje relację między 2 klasami:... jest szególnym przypadkiem...,... jest rodzajem... rzadziej stosowana i trudniejsza technika od kompozycji Komputer Samochód Figura Trójkąt Czworokąt Notebook Ciężarówka Wyścigówka Prostokąt Kwadrat

Dziedziczenie w kodzie class Figura {... class Trojkat extends Figura {... class Czworokat extends Figura {... class Prostokat extends Czworokat {... class Kwadrat extends Prostokat {... Klasa bazowa Nadklasa Klasa dziedziczona Base class Super class Figura Klasa dziedzicząca Podklasa Derived class Base class Subclass Trójkąt Czworokąt Prostokąt Kwadrat

Dziedziczenie jako zawieranie się podzbiorów każdy kwadrat jest prostokątem wśród prostokątów niektóre są szczególne: kwadraty kwadrat zatem dziedziczy z prostokąta CZWOROKĄTY FIGURY Figura TROJKĄTY PROSTOKĄTY Trójkąt Czworokąt KWADRATY Prostokąt Kwadrat

Konsekwencje dziedziczenia klasa dziedzicząca przejmuje kod z klasy bazowej: class Figura { Punkt srodek; public void przesun(int dx, int dy) { srodek.przesun (dx, dy); class Kolo extends Figura { int r;... Kolo k = new Kolo(); k.srodek = new Punkt(5,5); k.r = 3; k.przesun(1,0); korzyści: mniej kodowania propagowanie zmian

Konstruktory w dziedziczeniu Konstruktory nie dziedziczą się!!! class Figura { Punkt srodek; public Figura(Punkt s) { srodek = new Punkt(s); class Kolo extends Figura { int r; public Kolo(Punkt s, int rr) { srodek=new Punkt(s); r=rr;... Figura f=new Figura( new Punkt(0,0)); Kolo k = new Kolo ( new Punkt(10,10), 5); ale to się nie skompiluje dlaczego?

Obiekty klas dziedziczących tworzą się po kolei aż 4 obiekty (5)!!! Kwadrat k = new Kwadrat(new Punkt(1,1), 10)); Figura środek 1 2 3 4 Czworokąt Figura środek Prostokąt Czworokąt Figura środek Kwadrat Prostokąt Czworokąt Figura środek new Figura(...) new Czworokat(...) new Prostokat(...) new Kwadrat(...) a każdy obiekt to wywołanie konstruktora który potrzebuje parametrów który konstruktor ma się wywołać (przeciążanie)?

Porządek wywołania konstruktorów każdy konstruktor klasy dziedziczącej musi wskazać konkretny konstruktor klasy bazowej, który wywoła się przed nim: nazwa klasy bazowej zastępowana jest słowem super konstruktor wybiera się podając jego parametry (przeciążanie!) wskazanie to musi być pierwszą instrukcją konstruktora jeśli tego nie zrobi kompilator wskaże konstruktor domyślny: class B extends A { public B() { public B() { super(); tu: zanim wywoła się domyślny konstruktor klasy B przed nim wywoła się domyślny konstruktor klasy A

Przykład wywołań konstruktorów class A { public A() { System.out.println("A.A()"); public A(int i) { System.out.println("A.A(int)"); class B extends A { public B() {super(0);system.out.println("b.b()"); public B(int i) {System.out.println("B.B(int)"); class C extends B { public C() { System.out.println("C.C()"); public C(int i) {super(i);system.out.println("c.c(int)"); A.A() A.A(int)... new C(); new C(1); A.A(int) B.B() C.C() A.A() B.B(int) C.C(int) B.B() C.C() B.B(int) C.C(int)

Konstruktory jeszcze raz brakuje konstruktora domyślnego Figury class Figura { Punkt srodek; public Figura(Punkt s) { srodek = new Punkt(s); class Kolo extends Figura { int r; public Kolo(Punkt s, int rr) { super(); srodek=new Punkt(s); r=rr; to wstawia kompilator... Figura f=new Figura( new Punkt(0,0)); Kolo k = new Kolo ( new Punkt(10,10), 5); lub wskazania innego konstruktora i jego parametrów

Konstruktory jeszcze raz wskazanie właściwego konstruktora class Figura { Punkt srodek; public Figura(Punkt s) { srodek = new Punkt(s); class Kolo extends Figura { int r; public Kolo(Punkt s, int rr) { super(s); srodek=new Punkt(s); r=rr;... Figura f=new Figura( new Punkt(0,0)); Kolo k = new Kolo ( new Punkt(10,10), 5); przy okazji inicjacja odziedziczonego pola który powinien być... prywatny?

Hermetyzacja w dziedziczeniu czy prywatne pola/metody się dziedziczą? class Figura { private Punkt srodek; public Figura(Punkt s) { srodek = new Punkt(s); class Kolo extends Figura { int r; public Kolo(Punkt s, int rr) { super(s); r=rr; public void przesun(int dx, int dy) { srodek.przesun(dx, dy); BŁĄD HERMETYZACJI dziedziczą się, ale są niedostępne! metoda 'przesun' powinna być zdefiniowana w Figurze albo należy użyć nowego poziomu ochrony... `

Poziom ochrony 'protected' pośredni poziom między 'public' a 'private' publiczny dla rodziny (w drzewie dziedziczenia) prywatny dla innych (obcych) klas class Figura { protected Punkt srodek; public Figura(Punkt s) { srodek = new Punkt(s); class Kolo extends Figura { int r; public Kolo(Punkt s, int rr) { super(s); r=rr; public void przesun(int dx, int dy) { srodek.przesun(dx, dy); OK `... Figura f=new Figura( new Punkt(0,0)); f.srodek=null; BŁĄD Kolo k = new Kolo ( new Punkt(10,10), 5); System.out.println(k.srodek); BŁĄD

Dziedziczenie nie dziedziczy się: konstruktorów (destruktorów, operatora= w C++) dziedziczy się: pola metody typ `

Po co typ? kompilator pilnuje zgodności typów: int i; float f; i = f; BŁĄD void f(int a) {... f( abc ); BŁĄD Samochód s = new Komputer(); BŁĄD ale czasami można go oszukać rzutowanie (casting) ` i = (int)f; OK Samochód s = (Samochód)new Komputer(); BŁĄD

Dziedziczenie typu klasa Kwadrat ma 4 typy (5): Figura Czworokat Prostokat Kwadrat więc kompilator dopuści podstawienie: Figura f = new Kwadrat(...); rzutowanie w górę!!! (upcasting) ` Figura Czworokąt Prostokąt Kwadrat

Rzutowanie w górę Figura[] figury = new Figura[100]; figura[0] = new Kwadrat(...); figura[1] = new Prostokat(...); figura[2] = new Trojkat(...); rzutowanie to zachodzi tylko w dziedziczeniu zawsze jest możliwe i bezpieczne upraszcza przechowywanie obiektów z 1 rodziny `

Klasa Object dlaczego Kwadrat ma 5 typów? każda klasa w Javie dziedziczy z klasy 'Object' (bezpośrednio lub pośrednio) class Figura {... class Figura extends Object {... pojedyncze drzewo dziedziczenia Object Figura składowe klasy Object: public String tostring(); public boolean equals(object o); metody związane z wątkami referencja typu 'Object' Object o = new... ` Czworokąt Prostokąt Kwadrat

Utrata dostępu do informacji Figura[] figury; for (Figura f: figury) f.przesun(1, 0); ale Figura f = new Kolo(new Punkt(1,2), 10); System.out.println(f.getR()); skąd wiadomo że 'f' to Koło? Figura f; if (random.nextint(2)%2 == 0) f = new Kolo(new Punkt(1,2), 10); else f = new Prostokat(new Punkt(1,2), 4, 6);

Utrata dostępu do informacji obiekt Koło cały czas jest w pamięci nie zmienia typu!!! (obiekt raz stworzony jako Koło zawsze będzie już Kołem) rzutowanie w górę zmienia tylko sposób patrzenia na obiekt kompilator mając referencję 'Figura f' nie zna rzeczywistego typu obiektu na który ona wskazuje wie, że ten obiekt to jakaś Figura i ma metodę 'przesun(int,int)' f - srodek:punkt +przesun(int,int) - r: int + getr(): int

Rzutowanie w dół (downcasting) rzutowanie z typu bazowego na typ pochodny ale to zły przykład: Kolo k = (Kolo)new Figura(...); dobry przykład: Figura f = new Kolo(...); Kolo k = (Kolo)f; poprawne rzutowanie w dół może nastąpić tylko po wcześniejszym rzutowaniu w górę odzyskanie utraconego dostępu do informacji Object Figura Czworokąt Prostokąt Kwadrat rzutowanie w dół jest ryzykowne

Mechanizm RTTI f? identyfikacja typu w czasie wykonania programu (Run-Time Type Identification) umożliwia świadome i poprawne rzutowanie w dół if (f instanceof Kolo) { Kolo k = (Kolo)f; System.out.println(k.getR()); operator 'instanceof' bada, czy 'f ' ma typ 'Kolo' jego bezpośrednie używanie (nadużywanie) jest uważane za mało eleganckie

Wykorzystanie 'instanceof' policzenie figur w tablicy Figura[] figury={ new Kwadrat(...), new Prostokat(...), new Czworokat(...) int lczw, lprost, lkw=0; for (Figura f: figury) { if (f instanceof Kwadrat) ++ lkw; if (f instanceof Prostokat) ++ lprost; if (f instanceof Czworokat) ++ lczw; System.out.println( Kwadraty: +lkw); System.out.println( Prostokąty: +lprost); System.out.println( Czworokąty: +lczw); wynik: 1 2 3!!! przecież każdy prostokąt jest też czworokątem!!!

Wykorzystanie 'instanceof' alternatywne policzenie figur w tablicy... if (f instanceof Kwadrat) ++ lkw; else if (f instanceof Prostokat) ++ lprost; else if (f instanceof Czworokat) ++ lczw;... lub: if (f instanceof Kwadrat) ++ lkw; if ( f instanceof Prostokat &&! f instanceof Kwadrat) ++ lprost; if ( f instanceof Czworokat &&! f instanceof Prostokat) ++ lczw; Object Figura Czworokąt Prostokąt Kwadrat

Nadpisywanie składowych w dziedziczeniu składowe dziedziczą się ale dopuszczalne jest ich nadpisywanie: class A { int x; class B extends A { int x; w takiej sytuacji obiekt B ma 2 zmienne 'x'!!! w przypadku pól to zwykle pomyłka x x 5 3 B A

Nadpisywanie pól class A { int x; class B extends A { int x; class C extends B { int x; public void showall() { System.out.println("A.x="+A.x+",B.x="+super.x+",C.x="+x); C c = new C(); c.x = 30; c.showall(); ((B)c).x = 20; ((A)c).x = 10; c.showall(); ważny jest typ referencji!!! x x x 30 20 10 B A C

Nadpisywanie metod w zasadzie nadpisywanie metod działa tak samo ale w Javie jest specjalny mechanizm, który komplikuje sprawę: POLIMORFIZM przy wywołaniu metod nie jest ważny typ referencji (jak w przypadku pól) ważny jest typ obiekty który się za nią ukrywa f? metody wywoływane w ten sposób nazywane są metodami/funkcjami wirtualnymi

Nadpisywanie a przeciążanie (overriding vs overloading) to nie jest nadpisywanie tylko przeciążanie: class A { String f() { return A.f ; class B extends A { String f(int a) { return B.f ; class C extends B { String f(char c) { return C.f ; C c = new C(); System.out.println(c.f()); System.out.println(c.f(0)); System.out.println(c.f('a')); nadpisywanie: + A.f() + B.f(int) + C.f(char) C B A class A { String f() { return A.f ; class B extends A { String f() { return B.f ; class C extends B { String f() { return C.f ; System.out.println(c.f());??? + B.f() + C.f() + A.f() C B A

Wiązanie metod (binding) class A { public String f() { return A.f ; class B extends A { public String f() { return B.f ; class C extends B { public String f() { return C.f ; A a = new C(); System.out.println(a.f()); obiekt klasy C ma 3 metody 'f()' C B A + A.f(): String + B.f(): String + C.f(): String 0x02ca4 0x02cc4 0x02ce4 każda ma inny adres w pamięci kodu kompilator musi wskazać, którą metodę wywołać skompilować znaczy przetłumaczyć na asembler: a.f(); jump 0x02cc4? wiązanie metody

Wiązanie wczesne i późne jeśli kompilator faktycznie wiąże metodę wiązanie wczesne a.f(); jump 0x02ca4 jaką metodę wybiera? z tej klasy, jakiego typu jest referencja 'a' (A) jeśli kompilator nie wiąże kodu wiązanie późne a.f(); jump kiedy wykona się te wiązanie? w czasie wykonania programu (run-time) jaka metoda zostanie wybrana? z tej klasy, jakiego typu jest obiekt

Funkcje/Metody wirtualne metody wiązane wcześnie zwykłe metody metody wiązane późno metody wirtualne mechanizm późnego wiązania metod polimorfizm w Javie (prawie) wszystkie metody są wirtualne nie trzeba ich oznaczać (jak w C++ 'virtual') metody wirtualne mogą nieznacznie spowalniać wykonanie programu

Typowe użycie f. wirtualnych class Figura { public String opis(){return Jestem Figurą ; Trójkąt class Trojkat extends Figura { public String opis(){return Jestem Trójkątem ; class Czworokat extends Figura { public String opis(){return Jestem Czworokątem ; Figura Czworokąt Prostokąt Kwadrat class Prostokat extends Czworokat { public String opis(){return Jestem Prostokątem ; class Kwadrat extends Prostokat { public String opis(){return Jestem Kwadratem ;... Figura f=new??? System.out.println(f.opis());... System.out.println(xxx.opis());??? xxx

Metody niewirtualne w Javie wyjątkami (zwykłymi metodami) są metody: finalne statyczne prywatne class A { private String f() { return A.f ; public String g() { return A.g; public String call() { return f()+ +g(); class B extends A { private String f() { return B.f ; public String g() { return B.g;... A a = new B(); System.out.println(a.call());

Metody niewirtualne w Javie wyjątkami (zwykłymi metodami) są metody: finalne statyczne prywatne class A { private String f() { return A.f ; public String g() { return A.g; public String call() { return f()+ +g(); class B extends A { private String f() { return B.f ; public String g() { return B.g;... A a = new B(); System.out.println(a.call()); A.f B.g wywołanie wirtualne wywołanie niewirtualne

Jeszcze metody niewirtualne class A { private String f() { return A.f ; public String g() { return A.g; class B extends A { private String f() { return B.f ; public String g() { return B.g; public String call() { return f()+ +g();... A a = new B(); System.out.println(a.call());??? metoda 'call' w klasie B

Jeszcze metody niewirtualne class A { private String f() { return A.f ; public String g() { return A.g; class B extends A { private String f() { return B.f ; wywołanie wirtualne public String g() { return B.g; public String call() { return this.f()+ +this.g();... wywołanie niewirtualne A a = new B(); System.out.println(a.call()); B.f B.g 'this' w kodzie klasy A jest typu A 'this' w kodzie klasy B jest typu B

Poziom kodu class A { protected int x = 10; public int getax() { return x; class B extends A { protected int x = 20; public int getbx() { return x; x 10 class C extends B { protected int x = 30; x 20 public int getcx() { return x;... C c= new C(); x 30 System.out.println( +c.getax()+c.getbx()+c.getcx()); C B A

Poziom kodu class A { typu A protected int x = 10; public int getax() { return this.x; class B extends A { typu B protected int x = 20; public int getbx() { return this.x; class C extends B { typu C protected int x = 30; C public int getcx() { return this.x; # x +getcx()... C c= new C(); System.out.println( +c.getax()+c.getbx()+c.getcx()); 10 20 30 kod sięga do pola ze swojemu poziomu potem do pól odziedziczonych (do góry) A # x +getax() B # x +getbx() nigdy nie sięga w dół (do klas dziedziczących)

Klasy i metody finalne z klasy finalnej nie można dziedziczyć finall class Ostateczna {... class Nowa extends Ostateczna {... metody finalnej nie można nadpisać jest też metodą niewirtualną (m.in. szybciej się wykonuje wiązanie wczesne) class Prostokat { protected double a, b; public final double pole() { return a*b; public Prostokat(double aa, double bb) { a=aa; b=bb; class Kwadrat extends Prostokat { public Kwadrat(int a) { super(a, a); public double pole() { return...

Klasy abstrakcyjne z klasy abstrakcyjne nie można utworzyć obiektu abstract class Figura {... new Figura(...); klasa abstrakcyjna służy tylko do dziedziczenia class Kolo extends Figura {... class Trojkat extends Figura {... ale można tworzyć referencje typu abstrakcyjnego Figura f = null; Figura[] figury = new Figura[100]; f=new Kolo(...); figury[0] = new Trojkat(...); klasa abstrakcyjna to zwykła klasa: może mieć pola, metody, konstruktory klasa abstrakcyjna ma 1 przywilej: tylko ona może posiadać metody abstrakcyjne...

Metody abstrakcyjne metoda abstrakcyjna to metoda niedokończona, zawiera tylko nagłówek abstract class Figura { protected Punkt srodek; public abstract double pole(); używana kiedy jej definicja nie miałaby sensu (jak policzyć pole jakiejś nieokreślonej figury?) klasa która dziedziczy z klasy abstrakcyjnej metodę abstrakcyjną musi ją zdefiniować do końca class Kolo extends Figura { protected double r; public double pole() { return Math.PI*r*r; metoda abstrakcyjna nigdy nie będzie wywoływana: jest wirtualna a nigdy nie stworzy się obiekt klasy Figura

Po co metody abstrakcyjne? kompilator ma wywołanie: Figura f =... f.pole(); musi sprawdzić, czy w klasie Figura metoda 'pole()' nie jest np.: statyczna, finalna, prywatna niewirtualna metoda abstrakcyjna narzuca na klasy dziedziczące obowiązek posiadania kompletnej metody 'pole()' (jeśli same nie chcą być abstrakcyjne): abstract class Figura2D extends Figura { metoda abstrakcyjna definiuje interfejs hierarchii klas

Wywoływanie metod zastępowanych konstruktor klasy dziedziczącej woła konstruktor klasy bazowej nowa metoda wirtualna całkowicie zastępuje przesłanianą metodę metoda zastępujące może po raz ostatni wywołać metodę zastępowaną class Figura { public String opis() {return Jestem Figurą ; class Kolo extends Figura { public String opis(){return super.opis()+ i Kołem ;... Figura f=new Koło(); System.out.println(f.opis()); Jestem Figurą i Kołem

Metoda 'public String tostring()' metoda zdefiniowana w klasie 'Object' oryginalna definicja wypisuje rzeczywistą nazwę klasy i nr referencji zwraca tekstową reprezentację obiektu często wykorzystywana class Punkt extends Object { private x, y;... Punkt p=new Punkt (1,2); System.out.print(p);<==>System.out.print(p.toString()); Punkt@0x23cd można ją nadpisać i w nowej metodzie wywołać oryginalną definicję: class Punkt extends Object { private x, y; public String tostring() { return super.tostring+ (x: +x+,y: +y+ ) ; System.out.print(p); Punkt@0x23cd(x:1,y:2)

Hermetyzacja a funkcje wirtualne przy nadpisywaniu metod wirtualnych nie można zmniejszyć poziomu dostępności (zwiększyć poziomu ochrony): class Figura { public String opis(){return Jestem Figurą ; class Kolo extends Figura { protected String opis(){return Jestem Kołem ; // BŁĄD kompilacji poziom ochrony (dostępności) należy co najmniej zachować class Kolo extends Figura { public String opis(){return Jestem Kołem ; // BŁĄD kompilacji