Press "Enter" to skip to content

08.2: Używanie konstruktorów klas z klasami pochodnymi

Cele lekcji

Po zakończeniu tej lekcji…

  • Dowiesz się, w jaki sposób klasa podrzędna (pochodna) wywołuje konstruktora swojej klasy podstawowej.

 

Czas wyczyścić kod

Dodawanie konstruktora do klasy podstawowej jest bardziej złożone niż dodawanie go do klasy pozbawionej klas podrzędnych (pochodnych).

Po utworzeniu obiektu na podstawie klasy pochodnej konstruktor jest wykorzystywany zarówno dla tej klasy, jak i jej klasy podstawowej. Więc po dodaniu konstruktora niestandardowego do klasy podstawowej należy opracować sposób na przekazywanie do niego wartości przez klasę pochodną.

Po zastanowieniu ma to swój sens: korzystanie z konstruktora niestandardowego oznacza, że dane wartości są wymagane przed utworzeniem określonego obiektu. Gdy obiekt jest tworzony na podstawie klasy pochodnej, klasa podstawowa nadal musi zawierać określone wartości, więc należy je przekazać do konstruktora klasy pochodnej, który przekazuje je dalej — do konstruktora klasy podstawowej.

Poniżej znajduje się opis tej operacji.

 

Etap 1: Uruchom aplikację Visual Studio i otwórz swoje rozwiązanie.

 

Etap 2: W projekcie Engine kliknij dwukrotnie klasę Item i zacznij ją modyfikować. Po właściwościach dodaj następujące wiersze, aby utworzyć konstruktora:

public Item(int id, string name, string namePlural)
{
    ID = id;
    Name = name;
    NamePlural = namePlural;
}

 

UWAGA: Jeśli teraz spróbujesz skompilować rozwiązanie, zostaną wyświetlone błędy dotyczące klas HealingPotion i Weapon. To są właśnie klasy pochodne względem klasy Item i nie mają one żadnych wartości do przekazania do nowego konstruktora klasy Item.

 

Etap 3: Otwórz klasę HealingPotion i dodaj poniższe wiersze, aby utworzyć nowego konstruktora:

public HealingPotion(int id, string name, string namePlural, int amountToHeal) : base(id, name, namePlural)
{
    AmountToHeal = amountToHeal;
}

 

Konstruktor HealingPotion zawiera parametry dla jednej swojej właściwości (AmountToHeal) i trzech właściwości, których używa z klasy podstawowej (ID, Name i NamePlural).

W konstruktorze określana jest wartość właściwości AmountToHeal, która została przekazana przez parametr amountToHeal.

Po liście parametrów w konstruktorze występuje również kod:

base(id, name, namePlural)

 

Pobiera on wartości z parametrów w konstruktorze HealingPotion (id, name i namePlural) i przekazuje je do konstruktora klasy Item. W ten sposób parametry są wprowadzane do klasy podstawowej podczas tworzenia wystąpienia klasy pochodnej.

 

Etap 4: Zmodyfikuj klasę Weapon, dodając następujący kod konstruktora:

public Weapon(int id, string name, string namePlural, int minimumDamage, int maximumDamage) : base(id, name, namePlural)
{
    MinimumDamage = minimumDamage;
    MaximumDamage = maximumDamage;
}

 

Teraz możesz skompilować rozwiązanie. Klasy pochodne przekazują wymagane wartości do klasy podstawowej, więc kompilacja przebiegnie bez problemów.

 

Etap 5: Zmodyfikuj klasę LivingCreature i dodaj kod konstruktora:

public LivingCreature(int currentHitPoints, int maximumHitPoints)
{
    CurrentHitPoints = currentHitPoints;
    MaximumHitPoints = maximumHitPoints;
}

 

I ponownie: jeśli teraz spróbujesz skompilować rozwiązanie, zostaną wyświetlone błędy dotyczące klas Player i Weapon (czyli klas pochodnych względem LivingCreature).

 

Etap 6: Zmodyfikuj klasę Monster i wstaw następującego konstruktora:

public Monster(int id, string name, int maximumDamage, int rewardExperiencePoints, int rewardGold, int currentHitPoints, int maximumHitPoints)
            : base(currentHitPoints, maximumHitPoints)
{
    ID = id;
    Name = name;
    MaximumDamage = maximumDamage;
    RewardExperiencePoints = rewardExperiencePoints;
    RewardGold = rewardGold;
}

 

 Etap 7: Wstaw kod konstruktora w klasie Player:

public Player(int currentHitPoints, int maximumHitPoints, int gold, int experiencePoints, int level) : base(currentHitPoints, maximumHitPoints)
{
    Gold = gold;
    ExperiencePoints = experiencePoints;
    Level = level;
}

 

Wykonanie kompilacji teraz spowoduje wygenerowanie błędu spowodowanego tym, że w kodzie interfejsu użytkownika SuperAdventure tworzymy wystąpienie obiektu Player bez żadnych parametrów. W klasie Player mamy już nasz konstruktor niestandardowy, więc musimy go użyć i przekazać prawidłowe parametry.

 

Etap 8: W projekcie SuperAdventure prawym przyciskiem myszy kliknij pozycję SuperAdventure.cs i wybierz polecenie View Code. Wiersz 23 zmodyfikuj, aby wyglądał tak:

_player = new Player(10, 10, 20, 0, 1);

 

Teraz już przekazujemy wszystkie wartości w konstruktorze, więc w celu ustawienia właściwości obiektu Player, można usunąć wiersze 25-29, w których właściwości były ustawiane oddzielnie.

Wiersze 25-29 można pozostawić w kodzie i będą one normalnie działać, a program nie ulegnie uszkodzeniu. Jednak już określamy wartości tych właściwości, więc wiersze te można usunąć, oczyszczając jednocześnie kod.

 

Podsumowanie

Średniej wielkości programy praktycznie zawsze korzystają z dziedziczenia, a po zakończeniu tej lekcji już potrafisz utworzyć niestandardowy konstruktor działający w klasach używających dziedziczenia.

Stosowanie tego rozwiązania w naszej prostej grze może być uznawane za przerost formy nad treścią, jednak programista tworzący aplikacje w językach obiektowych powinien znać zasady dziedziczenia. Mam nadzieje, że dzięki prostym przykładom i niewielkim klasom, których tutaj użyliśmy, rozumiesz już, czym jest dziedziczenie.

Łącza do tej lekcji

Kod źródłowy w serwisie GitHub

Kod źródłowy w serwisie Dropbox

    Leave a Reply

    Your email address will not be published. Required fields are marked *