Kolejny wpis poświęcony programowaniu w Javie! Fajnie widzieć gdy strona kursu programowania wypełnia się kolejnymi lekcjami! W Poprzednich dwóch wpisach, przedstawiłem wam o co chodzi z tymi interfejsami w Javie, jak można je wykorzystać oraz dlaczego są tak ważne. Dziś porozmawiamy o kolejnym niezwykle istotnym elemencie jakim są klasy abstrakcyjne!
01. Klasa abstrakcyjna
Zanim przejdziemy do klas abstrakcyjnych, małe przypomnienie o jednym z pierwszych postów! O zwykłych klasach rozmawialiśmy w TYM poście, warto sobie przypomnieć czym właściwie jest klasa, oraz odświeżyć sobie jaka jest różnica między klasą a obiektem 😊 Wszystko znajdziecie w lekcji Pakiety, klasy, obiekty oraz podstawowe typy danych.
Klasa abstrakcyjna, różni się od zwykłej klasy już na poziomie jej deklaracji, występuje tutaj słowo kluczowe abstract. Prosty przykładzik:
public abstract class SimpleAbstract { }
Jak wcześniej napisałem, słowo abstract w deklaracji klasy mówi nam o tym że mamy do czynienia z klasą abstrakcyjną. Jednak w tym przypadku nasza klasa abstrakcyjna nie dostarcza nam żadnej funkcjonalności, ale spokojnie, jeszcze do tego dojdziemy 😊
02. Podstawowe informacje o klasie abstrakcyjnej
Jak wcześnie zostało to już powiedziane, klasa abstrakcyjna posiada w swojej deklaracji słowo abstracrt. To czyni ją klasą abstrakcyjną. Najważniejszą sprawą jest że klasa abstrakcyjna musi być rozszerzona, a jej abstrakcyjne metody zaimplementowane (no, to jest troszeczkę naciągnięcie, ale za chwilkę sprostuje tę wypowiedź).
Pamiętacie lekcje z interfejsami (Podstawy, Część druga)? Pojawiło się tam słówko kluczowe implements, w kontekście rozmowy o klasach abstrakcyjnych mówimy o rozszerzaniu klasy. Robimy to przy użyciu słowa extends.
Dodajmy do naszej prostej klasy abstrakcyjnej prostą metodę:
public abstract class SimpleAbstract { public void run() { System.out.println("SimpleAbstract run"); } }
Oraz tworzymy prostą klasę która będzie rozszerzać naszą abstrakcję:
public class SimpleClass extends SimpleAbstract { }
W tym momencie możemy użyć naszej klasy:
SimpleClass simpleClass = new SimpleClass(); simpleClass.run();
Czas na małe sprostowanie, wcześniej napisałem że klasa abstrakcyjna musi zostać rozszerzona, nie jest to do końca prawda, Java pozwala nam utworzyć instancje klasy anonimowej, jednak podczas tworzenia obiektu, musimy zapewnić implementacje wszystkich metod.
SimpleAbstract simpleAbstract = new SimpleAbstract() { @Override public void run() { //Implementation } };
W sytuacji kiedy mamy tylko jedną metodę, możemy się jeszcze o taki zapis pokusić, jednak staje się to mocno niepraktyczne w momencie kiedy klasa abstrakcyjna posiada troszkę większą logikę 😉
03. Metody abstrakcyjne
Przede wszystkim należy wspomnieć o metodach abstrakcyjnych. Metody abstrakcyjne zostały już omówione w poprzedni lekcjach o interfejsach (Część pierwsza, Część druga). Metody abstrakcyjne w klasach abstrakcyjnych posiadają słowo kluczowe abstract, i muszą posiadać implementację w klasach które rozszerzają klasę abstrakcyjną.
Dołóżmy do naszej klasy abstrakcyjnej, jedną abstrakcyjną metodę:
public abstract class SimpleAbstract { public void run() { System.out.println("SimpleAbstract run"); } public abstract void someMethod(); }
W tym momencie klasa która ją rozszerza musi zaimplementować abstrakcyjną metodę:
public class SimpleClass extends SimpleAbstract { @Override public void someMethod() { System.out.println("Lets code!"); } }
04. Konstruktor
Ciekawie wygląda sytuacja, w momencie kiedy przyjrzymy się jaka jest hierarchia tworzenia danego obiektu. Aby uzmysłowić sobie ten proces, w obu klasach dodamy konstruktor który wypisze nam na konsolę kiedy został wywołany.
public abstract class SimpleAbstract { public SimpleAbstract() { System.out.println("SimpleAbstract constructor"); } public void run() { System.out.println("SimpleAbstract run"); } public abstract void someMethod(); }
public class SimpleClass extends SimpleAbstract { public SimpleClass() { System.out.println("SimpleClass constructor"); } @Override public void someMethod() { System.out.println("Lets code!"); } }
Tworzymy nasz obiekt w taki sam sposób jak zazwyczaj:
SimpleClass simpleClass = new SimpleClass();
Jak myślisz, w jakiej kolejności wykonają się konstruktory?
SimpleAbstract constructor SimpleClass constructor
Pierwszy zostanie utworzony rodzic! Czyli klasa abstrakcyjna! Dopiero po utworzeniu rodzica, tworzy się jego dziecko!
05. Podsumowanie
W telegraficznym skrócie przedstawię wszystkie najważniejsze informacje dotyczące klas abstrakcyjnych.
- Klasa abstrakcyjna posiada słowo kluczowe abstract.
- Klasa abstrakcyjna może posiadać abstrakcyjne, oraz nie abstrakcyjne metody.
- Możemy utworzyć bezpośrednio instancję z klasy abstrakcyjnej, jednak musimy podczas tworzenia zapewnić implementację wszystkich zadeklarowanych metod.
- Klasa abstrakcyjna może posiadać metody finalne (metody które nie mogą zostać nadpisane)
- Klasa abstrakcyjna może posiadać metody statyczne (metody które możemy użyć bez tworzenia konkretnej instancji)
- Klasa abstrakcyjna może posiadać konstruktor, który zawsze wykona się przed konstruktorem klasy która rozszerza daną abstrakcję.
- Klasa abstrakcyjna, tak samo jak normalna klasa może posiadać swoje pola.
Ostatnią, oraz jedną z najważniejszych rzeczy jakie należy powiedzieć o klasach abstrakcyjnych, jest to, iż klasa może rozszerzać tylko jedną klasę abstrakcyjną! W odróżnieniu od interfejsów, których jedna klasa może implementować wiele.
Zdaje się że to najważniejsze informacje które dotyczące klas abstrakcyjnych. Pozostaje jeszcze pytanie kiedy używać interfejsów, a kiedy klas abstrakcyjnych, ale tym tematem zajmiemy się w jednym z kolejnych części kursu programowania w Javie! 😊