Każda nowa wersja Javy różni się od poprzednich. Oto przykład zmian w materiale, który omówiliśmy: przed Javą 5 język nie miał
Podobnie, Java 8 znacznie różni się od Java 7. Większość naszych lekcji została napisana dla 7. wersji języka, ale oczywiście nie będziemy ignorować ważnych innowacji. Ponieważ w tej lekcji omawialiśmy już interfejsy, rozważymy jedną aktualizację — domyślne metody w interfejsach . Wiesz już, że interfejs nie implementuje zachowania . Jego zadaniem jest opisanie zachowania, jakie muszą posiadać wszystkie obiekty, które go implementują. Jednak programiści często spotykali się z sytuacjami, w których implementacja metody jest taka sama we wszystkich klasach. Rozważmy przykład naszego starego samochodu:
enum
s. 
public interface Car {
public void gas();
public void brake();
}
public class Sedan implements Car {
@Override
public void gas() {
System.out.println("Gas!");
}
@Override
public void brake() {
System.out.println("Brake!");
}
}
public class Truck implements Car {
@Override
public void gas() {
System.out.println("Gas!");
}
@Override
public void brake() {
System.out.println("Brake!");
}
}
public class F1Car implements Car {
@Override
public void gas() {
System.out.println("Gas!");
}
@Override
public void brake() {
System.out.println("Brake!");
}
}
"Jaki Twoim zdaniem jest główny problem z tym kodem? Pewnie zauważyłeś, że napisaliśmy kilka powtarzających się kodów! Ten problem jest powszechny w programowaniu i musisz go unikać. To inna sprawa, że określone rozwiązania wcześniej nie istniały Została wydana Java 8. Wraz z tą wersją pojawiła się możliwość określania domyślnych metod i implementowania ich bezpośrednio w interfejsie! Oto jak to zrobić:
public interface Car {
public default void gas() {
System.out.println("Gas!");
}
public default void brake() {
System.out.println("Brake!");
}
}
public class Sedan implements Car {
}
public class Truck implements Car {
}
public class F1Car implements Car {
}
Teraz metody gas()
i brake()
, które były takie same dla wszystkich samochodów, zostały przeniesione do interfejsu. Nie jest potrzebny żaden powtarzający się kod. Co więcej, metody są dostępne na każdych zajęciach!
public class Main {
public static void main(String[] args) {
F1Car f1Car = new F1Car();
Sedan sedan = new Sedan();
Truck truck = new Truck();
truck.gas();
sedan.gas();
f1Car.brake();
}
}
Co jeśli istnieje 100 klas z tą gas()
metodą, ale tylko 99 z nich zachowuje się tak samo? Czy to wszystko psuje i sprawia, że domyślna metoda nie nadaje się do tej sytuacji? Oczywiście, że nie :) Domyślne metody w interfejsach można nadpisywać w taki sam sposób, jak zwykłe.
public class UnusualCar implements Car {
@Override
public void gas() {
System.out.println("This car accelerates differently!");
}
@Override
public void brake() {
System.out.println("This car decelerates differently!");
}
}
Wszystkie 99 innych typów samochodów zaimplementuje metodę domyślną, aUnusualCar
class, która jest wyjątkiem, nie psuje ogólnego obrazu i spokojnie definiuje własne zachowanie. Wielokrotne dziedziczenie interfejsów. Jak już wiesz, Java nie obsługuje wielokrotnego dziedziczenia. Istnieje wiele powodów. Przyjrzymy się im szczegółowo w osobnej lekcji. Inne języki, takie jak C++, obsługują to. Bez wielokrotnego dziedziczenia pojawia się poważny problem: jeden obiekt może mieć kilka różnych cech i „zachowań”. Oto przykład z życia: jesteśmy dziećmi dla naszych rodziców, uczniami dla naszych nauczycieli i pacjentami dla naszych lekarzy. W życiu przyjmujemy różne role iw związku z tym inaczej się zachowujemy: oczywiście nie rozmawialibyśmy z nauczycielami tak, jak rozmawiamy z naszymi bliskimi przyjaciółmi. Spróbujmy przełożyć to na kod. Wyobraź sobie, że mamy dwie klasy: Staw i Woliera. Do stawu potrzebujemy ptactwa wodnego; do woliery potrzebujemy latających ptaków. W tym celu stworzyliśmy dwie klasy bazowe:FlyingBird
i Waterfowl
.
public class Waterfowl {
}
public class FlyingBird {
}
W związku z tym wyślemy ptaki, których klasy dziedziczą FlyingBird
do woliery, a ptaki, które dziedziczą, wyślemy Waterfowl
do stawu. Wszystko wydaje się bardzo proste. Ale gdzie wysłać kaczkę? Pływa i lata. I nie mamy wielokrotnego dziedziczenia. Na szczęście Java obsługuje wiele implementacji interfejsów. Chociaż klasa nie może dziedziczyć kilku rodziców, może z łatwością zaimplementować kilka interfejsów! Nasza kaczka może być zarówno latającym ptakiem, jak i ptactwem wodnym :) Aby osiągnąć zamierzony efekt, musimy po prostu stworzyć FlyingBird
i interfejsy, a nie klasy.Waterfowl
public class Duck implements FlyingBird, Waterfowl {
// The methods of both interfaces can be easily combined into one class
@Override
public void fly() {
System.out.println("Fly!");
}
@Override
public void swim() {
System.out.println("Swim!");
}
}
W związku z tym nasz program zachowuje elastyczność klas, aw połączeniu z metodami domyślnymi nasze możliwości definiowania zachowania obiektów stają się niemal nieograniczone! :)
GO TO FULL VERSION