2012-11-23 12 views
11

Nowość w OOP i jestem zdezorientowany przez działanie konstruktorów klasy pochodnej podczas dziedziczenia z klasy bazowej w języku C#.Parametry konstruktora i dziedziczenie

Pierwsza klasa bazowa:

class BaseClass 
{ 
    private string BaseOutput = null; 

    public BaseClass(string BaseString) 
    { 
     BaseOutput = BaseString; 
    } 

    public virtual void PrintLine() 
    { 
     Console.WriteLine(BaseOutput); 
    } 
} 

Oto klasa pochodna:

class SubClass : BaseClass 
{ 
    private string SubOutput = null; 

    public SubClass(string BaseString, string SubString) : base(BaseString) 
    { 
     SubOutput = SubString; 
    } 

    public override void PrintLine() 
    { 
     Console.WriteLine(SubOutput); 
    } 
} 

Wreszcie główną częścią programu:

class Program 
{ 
    static void Main(string[] args) 
    { 
     BaseClass theBase = new BaseClass("Text for BaseClass"); 
     SubClass theSub = new SubClass("2nd param", "Text for SubClass"); 

     theBase.PrintLine(); 
     theSub.PrintLine(); 

     Console.ReadKey(); 
    } 
} 

Czego nie robić get jest, dlaczego, wywołując konstruktora dla klasy pochodnej, muszę również przekazać parametr, którego potrzebuje klasa bazowa. Czy pole BaseOutput w klasie pochodnej nie powinno pozostać ustawione na null, jeśli nie przypisano do niego żadnej wartości? Dlaczego nie coś podobnego do tego dzieła może:

public SubClass(string SubString) : base(BaseString) 

Ponadto podczas wywoływania konstruktora w tej klasie pochodnej, pierwszy parametr musi być nazwany tak samo jak w klasie bazowej lub inny zgłasza błąd. Gdybym miał określić nową zmienną string o nazwie AnotherString w klasie pochodnej, dlaczego nie będzie to praca:

public SubClass(string AnotherString, string SubString) : base(BaseString) 

Wreszcie, kiedy to zrobić we właściwy sposób i wpisać się to ...

public SubClass(string BaseString, string SubString) : base(BaseString) 

... do czego służy pierwszy parametr w konstruktorze SubClass? Nie jest on przypisywany ani używany w żadnych metodach dla mojej klasy pochodnej. Dlaczego w ogóle muszę go tam umieścić?

+0

Jest przechowywany przez ułamek sekundy, dopóki nie wywołasz konstruktora podklas. Następnie zastępujesz go ciągiem parametrów "2nd param". –

Odpowiedz

14

Na pytanie dlaczego nie można zrobić:

public SubClass(string SubString) : base(BaseString) 

Co by było BaseString?

Można zrobić:

public SubClass(string SubString) : base("SomeFixedString") 

lub

public SubClass(string SubString) : base(SubString) 

Ale jeśli chcesz zdać jeden ciąg parametru klasy bazowej konstruktora i mieć dodatkowy jeden, będziesz musiał przyjąć dwa parametry.

Jeśli chcesz zachować tę samą nazwę, nie musisz , nie. Możesz zrobić:

public SubClass(string AnotherString, string SubString) : base(AnotherString) 

Co do ostatniego pytania, pierwszy parametr nie robi nic, jest przekazywany do konstruktora klasy podstawowej. Możesz go użyć do czegoś innego, jeśli chcesz.

+0

Teraz to ma dla mnie dużo więcej sensu, dziękuję. "BaseClass" potrzebuje informacji, które należy przekazać do swojego konstruktora i pobiera to z tego, co wstawiasz do konstruktora pochodnego. – Frank

1

Jeśli chcesz zainicjować BaseString z wartości domyślnej, a następnie przekazać tę wartość do bazy konstruktora klasy (więc nie trzeba przekazać ten parametr do konstruktora klasy pochodnej)

public SubClass(string SubString) : base(null) 

lub zdefiniować konstruktor bez parametrów w klasa podstawowa.

Również o nazwie parametru - nie ma znaczenia, która nazwa ma parametr, który przekazujesz do konstruktora pochodnego. Ważna jest tylko wartość, którą przechodzisz do konstruktora bazowego.

public SubClass(string AnotherString, string SubString) : base(AnotherString) 
1
public SubClass(string BaseString, string SubString) : base(BaseString) 

Ten konstruktor w klasie pochodnej mówi, że po odebraniu dwóch argumentów BaseString i SubString, zadzwoń do konstruktora klasy bazowej z BaseString.

Zatem robi

public SubClass(string a, string b) : base(BaseString) 

nie działa, bo mówisz to wywołać konstruktora klasy bazowej z BaseString ale nie ma argumentu o nazwie BaseString.

Jeśli chcesz instancję klasy pochodnej bez przechodzenia String do konstruktora klasy bazowej, klasa bazowa potrzebuje domyślnego konstruktora:

public BaseClass() { } 
1

Jeśli chcesz okazją do NIE klasa pochodna aby ustawić basestring, to trzeba zapewnić domyślnego konstruktora w klasie bazowej tak:

public BaseClass() 
{ 

} 

Teraz w klasie pochodnej, ty może wywołać konstruktor bez argumentów w klasie bazowej jak ten:

public SubClass(string AnotherString) 
    : base() 
{ 
    // base() => explicit call to default construct in the base class. 
    // Do something else 
} 

ten zapewnia dobre praktyki inżynierii oprogramowania: jeśli chcesz, aby zapewnić możliwość nie ustawić ciąg klasy bazowej, a następnie zrobić w klasie bazowej . Inne "hacki", takie jak przekazywanie wartości null jako argumentu do konstruktora bazowego, służą jedynie do majsterkowania z elementami wewnętrznymi klasy podstawowej w sposób, który nie powinien być wykonywany z podklas.

+0

Po przeczytaniu niektórych innych odpowiedzi, zdecydowanie widzę wartość domyślnego konstruktora. Zrobię to od teraz zamiast przekazywać fałszywe wartości, dzięki! – Frank