Konstruktor klasy bazowej

0

Cześć

Zrobiłem konstruktor w klasie bazowej:

class Account
    {
        public string AccountNumber;
        public decimal Balance;
        public string FirstName;
        public string LastName;
        public long Pesel;
 
        public Account( string accountNumber, decimal balance, string firstName, string lastName, long pesel)
        {
            AccountNumber = accountNumber;
            Balance = balance;
            FirstName = firstName;
            LastName = lastName;
            Pesel = pesel;
        }
}

Dodałem go do klasy pochodnej:

    class BillingAccount : Account
    {
        public BillingAccount(string accountNumber, decimal balance, string firstName, string lastName, long pesel)
             : base(accountNumber, balance, firstName, lastName, pesel)
        {

        }
}

Jak to działa, że nie mogę teraz zrobić w klasie pochodnej innego konstruktora? Np. takiego:

        public BillingAccount(string firstName)
        {
            FirstName = firstName;
        }

Dostaję komunikat > Nie podano argumentu odpowiadającego wymaganemu parametrowi formalnemu „accountNumber” elementu „Account.Account(string, decimal, string, string, long)"

Co stoi na przeszkodzie, żeby zrobić konstruktor jedno argumentowy i tworzyć takie obiekty?

1

W drugim konstruktorze nie wywołałeś konstruktora klasy bazowej.

1

https://docs.microsoft.com/pl-pl/dotnet/csharp/programming-guide/classes-and-structs/using-constructors

In a derived class, if a base-class constructor is not called explicitly by using the base keyword, the parameterless constructor, if there is one, is called implicitly.
...
If a base class does not offer a parameterless constructor, the derived class must make an explicit call to a base constructor by using base.

0
Delor napisał(a):

https://docs.microsoft.com/pl-pl/dotnet/csharp/programming-guide/classes-and-structs/using-constructors

In a derived class, if a base-class constructor is not called explicitly by using the base keyword, the parameterless constructor, if there is one, is called implicitly.
...
If a base class does not offer a parameterless constructor, the derived class must make an explicit call to a base constructor by using base.

Ja bym chciał użyć tylko jednego pola z klasy bazowej, jak mam się odwołać do konstruktora?

EDIT: Przychodzi mi tylko do głowy zrobienie konstruktora jedno argument-owego w klasie bazowej ale nie chciał bym tego tak robić.

1

Zrob drugi konstruktor w bazowej

2
  1. Stwórz konstruktor bezparametrowy w klasie bazowej.
  2. Stwórz konstruktor jednoargumentowy w klasie bazowej i go wywołaj.
  3. Wywołaj bazowy konstruktor pięcioargumentowy z czterema parametrami ustawionymi na wartości domyślne.
  4. Wymyśl inne sposoby.
1

Jak nie chcesz wystawiać na zewnątrz konstruktora z bazowej to zrób protected. Ale generalnie zastanów się czy tego typu obiekt powinien posiadać pola FirstName itp. Czyli dotyczące chyba właściciela. Bo moim zdaniem raczej nie. A co jak ktoś chciałby mieć kilka kont?. Może się okazać, że jak wywalisz dane osoby to problem z konstruktorami zniknie.

0

Ogólnie to chodziło mi o to, żeby zrobić konstruktor jedno argumentowy w klasie pochodnej, niezależny od klasy bazowej (kod konstruktora miał być w klasie pochodnej).
Na co dzień pracuję w innym języku i tak jak tutaj, kiedy bym musiał coś kiedyś zmienić w konstruktorze klasy bazowej to musiał bym prze-kompilować wszystkie obiekty zależne. Zawsze dążymy do tego, żeby takich sytuacji unikać i stąd ten temat.

Pytanie wzięło się z tego, że nie rozumiem zależności kiedy klasa dziedziczy z innej i klasa bazowa ma swój konstruktor. Dla czego muszę odwoływać się do takiego konstruktora? Klasa pochodna nie może mieć "własnych" konstruktorów?

1

Może mieć. Ale chodzi o to, że jak bazowa ma tylko konstruktor parametrowy to pochodna musi go wywoływać. Taki urok tego języka (nie wiem jak w innych). Jeśli klasa bazowa nie ma konstruktora (lub ma bez parametrowy) to wtedy z dziedziczącej nie musisz go wywoływać. Tu masz fajnie to przedstawione: http://www.csharp411.com/c-object-initialization/

2

To nie jest kwestia języka, tylko kwestia zdrowego rozsądku i programowania obiektowego.

Masz klasę bazową, z której tworzysz obiekt. Obiekt to dane, zachowanie i tożsamość, gdzie to ostatnie można (w przybliżeniu) traktować jako konstruktor. Tworzenie obiektu to wywołanie jego konstruktora.

Jak zrobisz klasę pochodną, to obiekty tejże rozszerzają klasę bazową. Z tego wynika, że gdy tworzysz obiekt klasy pochodnej, to ten obiekt bazowy też musi zostać utworzony, a skoro musi być utworzony, to musi być wywołany jego konstruktor. To nie wynika z języka, tylko z semantyki, którą chcesz uzyskać, a jest nią chęć rozszerzenia klasy bazowej. Teraz w gestii języka są szczegóły odnośnie tego, że jak jest konstruktor bezparametrowy, to zostanie on wywołany implicite — to już szczegół implementacyjny, równie dobrze język mógłby zawsze wymagać wołania konstruktora klasy bazowej explicite.

Jeżeli chcesz mieć klasę pochodną i nie wywoływać konstruktora klasy bazowej, to tak naprawdę chcesz mieć zupełnie inną semantykę i powinieneś używać mixinów (ich w C# nie ma). Jeżeli i mixiny Ci nie pasują, to wchodzimy na grunt dyskusji o paradygmacie i semantyce modelu, ale wątpię, żeby taki był Twój cel.

1

Tak jak wcześniej ci wszyscy tłumaczyli , musisz zawsze wywołać konstruktor klasy bazowej albo lepiej - wszystkie pola muszą zostać zainicjowane. Czasem jest to robione jawnie w kodzie źródłowym a czasem niejawnie przez kompilator C# w kodzie IL.
Dlaczego tak, bo konstruktory inicjują pola klasy - przynajmniej w teorii bo czasem robi to CLR . Klasa potomna dziedziczy wszystko po klasie bazowej oprócz kontruktorów i finalizatorów.

1 użytkowników online, w tym zalogowanych: 0, gości: 1