JavaRush /Blog Java /Random-PL /Relacje pomiędzy klasami. Dziedziczenie, skład i agregacj...

Relacje pomiędzy klasami. Dziedziczenie, skład i agregacja

Opublikowano w grupie Random-PL
Cześć! Dzisiaj przyjrzymy się bliżej innej zasadzie programowania obiektowego (OOP) - dziedziczeniu. Jednocześnie będziemy badać inne typy relacji między klasami - kompozycję i agregację. Temat ten nie będzie trudny: z dziedziczeniem i jego przykładami spotkałeś się już wielokrotnie w poprzednich wykładach. Dziś najważniejsze będzie utrwalenie wiedzy, przyjrzenie się bliżej mechanizmowi dziedziczenia i jeszcze raz przerobienie przykładów :) No to do dzieła!
Relacje pomiędzy klasami.  Dziedziczenie, skład i agregacja - 1

Dziedziczenie w Javie i jego zalety

Jak zapewne pamiętasz, dziedziczenie to mechanizm pozwalający opisać nową klasę na podstawie już istniejącej (nadrzędnej). W tym przypadku właściwości i funkcjonalność klasy nadrzędnej są zapożyczane przez nową klasę. Przypomnijmy sobie przykład dziedziczenia z poprzednich wykładów:
public class Car {

   private String model;
   private int maxSpeed;
   private int yearOfManufacture;

   public Car(String model, int maxSpeed, int yearOfManufacture) {
       this.model = model;
       this.maxSpeed = maxSpeed;
       this.yearOfManufacture = yearOfManufacture;
   }


public void gas() {
       //...gaz
   }

public void brake() {
       //...hamulec
   }
}


public class Truck extends Car {

   public Truck(String model, int maxSpeed, int yearOfManufacture) {
       super(model, maxSpeed, yearOfManufacture);
   }
}



public class Sedan extends Car {
   public Sedan(String model, int maxSpeed, int yearOfManufacture) {
       super(model, maxSpeed, yearOfManufacture);
   }
}
Istnieje pewien program, w ramach którego pracujemy z różnymi typami samochodów. Nawet jeśli nie jesteś miłośnikiem motoryzacji, prawdopodobnie wiesz, że typów tych samych samochodów na świecie jest bardzo wiele :) Dlatego też dzielimy ogólne właściwości samochodów na wspólną klasę nadrzędną - Car. Co łączy wszystkie samochody, niezależnie od typu? Każdy samochód ma rok produkcji, nazwę modelu i maksymalną prędkość. Umieściliśmy te właściwości w polach model, maxSpeed, yearOfManufacture. Jeśli chodzi o zachowanie, każdy samochód może przyspieszać i hamować :) Definiujemy to zachowanie w metodach gas()i brake(). Jakie daje nam to korzyści? Przede wszystkim zmniejszenie ilości kodu. Oczywiście możemy obejść się bez klasy nadrzędnej. Ale ponieważ każdy samochód musi mieć możliwość przyspieszania i hamowania, będziemy musieli stworzyć metody gas()w brake()klasie Truck, w klasie Sedan, w klasie F1Car, w klasie Sportcari we wszystkich innych klasach samochodów. Wyobraź sobie, ile dodatkowego kodu napiszemy w tym przypadku. Nie zapomnij o polach model, maxSpeed ​​i yearOfManufacture: jeśli porzucimy klasę nadrzędną, utworzymy je w każdej z klas maszyn! Relacje pomiędzy klasami.  Dziedziczenie, skład i agregacja - 2 Kiedy będziemy mieli kilkadziesiąt klas maszyn, ilość powtarzalnego kodu stanie się naprawdę poważna. Przeniesienie wspólnych pól i metod (zwanych także „stanem” i „zachowaniem”) do klasy nadrzędnej pozwoli nam zaoszczędzić dużo czasu i miejsca. Jeśli dany typ ma właściwości lub metody, które są unikalne tylko dla niego i których nie ma w innych typach maszyn, nie ma to znaczenia. Zawsze można je utworzyć w klasie potomnej, oddzielnie od wszystkich pozostałych.
public class F1Car extends Car {

   public void pitStop() {

       //...tylko samochody wyścigowe robią pit stopy
   }

   public static void main(String[] args) {

       F1Car formula1Car = new F1Car();
       formula1Car.gas();
       formula1Car.pitStop();
       formula1Car.brake();
   }
}
Weźmy przykład samochodów wyścigowych Formuły 1. W przeciwieństwie do swoich „krewnych” zachowują się wyjątkowo - od czasu do czasu zatrzymują się w pit stopie. Nam to nie przeszkadza. Opisaliśmy już ogólne zachowanie klasy nadrzędnej Cari wewnątrz klas możemy dodać specyficzne zachowanie klas podrzędnych. Relacje pomiędzy klasami.  Dziedziczenie, skład i agregacja - 3 Dotyczy to również pól: jeśli klasa podrzędna ma unikalne właściwości, możemy spokojnie zadeklarować w niej te pola i nie martwić się :) Możliwość ponownego wykorzystania kodu to główna zaleta dziedziczenia. Dla programisty bardzo ważne jest, aby nie pisać niepotrzebnej ilości kodu. Spotkasz się z tym nie raz w swojej pracy. Proszę pamiętać o jeszcze jednej bardzo ważnej rzeczy: w Javie nie ma wielokrotnego dziedziczenia. Każda klasa dziedziczy tylko z jednej klasy. O przyczynach tego będziemy mówić bardziej szczegółowo w przyszłych wykładach, ale na razie pamiętajcie. To, nawiasem mówiąc, odróżnia Javę od niektórych innych języków OOP. Na przykład C++ ma wielokrotne dziedziczenie. Z dziedziczeniem wszystko jest mniej więcej jasne – przejdźmy dalej.

Skład i agregacja

Klasy i obiekty mogą być ze sobą powiązane. Dziedziczenie opisuje relację „jest” (lub po angielsku „IS A”). Lew jest zwierzęciem. Zależność tę można łatwo wyrazić za pomocą dziedziczenia, gdzie Animalklasa będzie rodzicem, a Lionklasa będzie dzieckiem. Jednak nie wszystkie relacje na świecie są opisywane w ten sposób. Na przykład klawiatura jest na pewno w jakiś sposób połączona z komputerem, ale nie jest komputerem . Dłonie są w jakiś sposób połączone z osobą, ale nią nie są. W tych przypadkach opiera się na innym typie relacji: nie „jest”, ale „jest częścią” („MA A”). Ręka nie jest osobą, ale jest częścią osoby. Klawiatura nie jest komputerem, ale jest częścią komputera. HAS Relacje można opisać w kodzie przy użyciu mechanizmów kompozycji i agregacji . Różnica między nimi polega na „ścisłości” tych powiązań. Podajmy prosty przykład: Mamy swoje Car- samochód. Każdy samochód ma silnik. Ponadto w każdym samochodzie znajdują się pasażerowie. Jaka jest podstawowa różnica między polami Engine enginei Passenger [] passengers? Jeśli w samochodzie jest pasażer А, nie oznacza to, że nie może w Bnim być pasażerów C. W jednym samochodzie może przebywać kilku pasażerów. Ponadto, jeśli wszyscy pasażerowie zostaną usunięci z samochodu, będzie on nadal działał cicho. Zależność między klasą Cara masą pasażerską Passenger [] passengersjest mniej rygorystyczna. Nazywa się to agregacją . Istnieje dobry artykuł na ten temat: Relacje między klasami (obiektami) . Stanowi kolejny dobry przykład agregacji. Załóżmy, że mamy klasę Studentoznaczającą ucznia i klasę StudentsGroup(grupę uczniów). Uczeń może być członkiem klubu fizyki, studenckiego fanklubu Gwiezdnych Wojen lub zespołu KVN. Kompozycja jest bardziej rygorystycznym rodzajem komunikacji. Podczas korzystania z kompozycji obiekt nie tylko jest częścią jakiegoś obiektu, ale także nie może należeć do innego obiektu tego samego typu. Najprostszym przykładem jest silnik samochodu. Silnik jest częścią samochodu, ale nie może być częścią innego samochodu. Jak widać, ich połączenie jest znacznie bardziej rygorystyczne niż połączenie Cari Passengers. Relacje pomiędzy klasami.  Dziedziczenie, skład i agregacja - 4
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION