2016-07-19 21 views
6

C# 6.0 w pigułce Josepha Albahari i Ben Albahari (O'Reilly).Kiedy powstają klasy konstruktorów zmuszonych do użycia podstawowego słowa kluczowego?

Prawa autorskie 2016 Joseph Albahari i Ben Albahari, 978-1-491-92706-9.

stany następujące na stronie 96, po wprowadzeniu niejawnej Wywołanie bez parametrów Base-konstruktora klasy:

Jeśli klasa bazowa nie ma dostępnego konstruktora bez parametrów, podklasy są zmuszeni użyć słowa kluczowego base w swoich konstruktorach.

Próbuję utworzyć fragment kodu, aby to potwierdzić, ale jeszcze się nie udało.

Moje urywek:

public class X 
{ 
    public int Num { get; set; } 

    public void Method_1() 
    { 
     Console.WriteLine("X"); 
    } 

    public virtual void Method_2() 
    { 
     Console.WriteLine(Num); 
    } 
} 

public class Y : X 
{ 
    public Y() 
    { 
     Num = 1000; 
    } 
} 

private static void Main(string[] args) 
{ 
    new Y().Method_2(); 
} 

Spodziewałem się, że pojawia się błąd kompilatora, po stwierdzeniu książki, ale mam żadnego. Kod działa i prawidłowo drukuje 1000.

Moje pytanie brzmi: co oznacza książka z podklasami zmuszonymi do użycia podstawowego słowa kluczowego? Próbuję odtworzyć taki scenariusz.

Czego mi brakuje?

Odpowiedz

10

klasy Yma mieć dostęp do konstruktora bez parametrów dla klasy bazowej, X, ponieważ jeśli klasa nie definiuje żadnego konstruktora, istnieje niejawny konstruktor bez parametrów.

Jeśli piszesz:

public class X 
{ 
    public X(int i){} 
} 

Wtedy nie będzie już być dostępny konstruktor bez parametrów z X w Y.

+0

Ale w jaki sposób wskazuje to na przypadek, w którym * podklasa jest zmuszona do użycia podstawowego słowa kluczowego *? – Veverke

+3

@Veverke - czy próbowałeś dodać ten konstruktor do swojej klasy 'X'? Jeśli tak, powinieneś zacząć otrzymywać błędy kompilatora. –

+0

@Damien_The_Unbeliever: dodanie takiego konstruktora zmusza mnie do zmiany aktualnego konstruktora Y, aby otrzymać również parametr in - lub alternatywnie do dodania konstruktora bez parametrów do X. Lub - mógłbym tylko dodać wywołanie base (0) do prądu Y konstruktor. W ostatnim przypadku * zostałem zmuszony do użycia podstawowego słowa kluczowego * (które jest jedynym pytaniem), chociaż nie ma sensu wywoływać konstruktora, który wymaga parametrów, których nie masz. Przynajmniej ten trzeci scenariusz, z 3, ilustruje ** jest zmuszony do użycia podstawowego słowa kluczowego **. – Veverke

5

Problem wynika z niezrozumienia przykładowego kodu. Ponieważ nie zdefiniowałeś żadnego konstruktora w , C# zdefiniował dla ciebie domyślną. Ten niejawny konstruktor jest konstruktorem bez arg.

Cytowany cytat odnosi się do przypadku, w którym faktycznie napisano konstruktor inny niż domyślny.

Zapisywanie niedomyślnego konstruktora blokuje generowanie niejawnego elementu pośredniczącego. Oznacza to jesteś zmuszony jawnie wywołać inny konstruktor z konstruktora klasy Dervived pomocą base słowa kluczowego

class BaseClass 
{ 
    public BaseClass(int i) {} 
} 

class Derived : BaseClass 
{ 
    public Derived() : base(44) { } 
} 
+0

To nie jest odpowiedź na pytanie. Pytam o to, co książka oznacza, * zmuszając do użycia podstawowego słowa kluczowego *. – Veverke

+1

Nie ma potrzeby tworzenia prywatnego konstruktora bez parametrów, o ile istnieje taki, który nie jest bez parametrów. – Servy

+0

@Servy dobry punkt. Zmieniona moja odpowiedź –

0

same zasady, z wyjątkiem ...

Jest to właściwie nie różni się od standardowych zasad dostępu członkach innego członka klasy bazowej.

Konstruktor to niewiele więcej niż zwykła funkcja.

Podstawową różnicą jest to, że klasa pochodna automatycznie próbuje wywołać konstruktora podstawowego. W szczególności konstruktor bazowy, który nie przyjmuje parametrów.

Jeśli nie istnieje żaden konstruktor, pojawi się błąd. Jeśli istnieje, ale nie masz "pozwolenia", aby uzyskać do niego dostęp, pojawi się błąd.

Jeśli nie określisz żadnych konstruktorów dla klasy bazowej, zakłada się, że ta klasa ma konstruktor bez parametrów, który nic nie robi.

Innymi słowy, jeśli nie zostanie określony konstruktor, zostanie on niejawnie utworzony.

Oto 7 przykłady, kiedy będzie i nie będzie zmierzyć się z tym problem:

Przykład 3 - OK - Implikowane domyślny pusty konstruktor

class Base 
    { 
     // No constructor explicitly defined so a default constructor is assumed 
     // Having no constructor at all is like having an empty constructor 
     // Like this: Base() { } 
    } 

    class Derived : Base 
    { 
     // OK - Explicitly calling accessible base constructor 
     public Derived() { } 
    } 

Przykład 2 - OK - Dostępna podstawa konstruktor

class Base { 
     // "public" so it's accessible by derived class 
     public Base() { } // no parameters - aka parameterless 
    } 

    class Derived : Base { 
     // OK - implicitly calls accessible parameterless constructor base() 
     public Derived() {} 
    } 

Przykład 3 - OK - Zabezpieczone środki nadal dostępne

class Base { 
     // "protected" so it's accessible by derived class 
     protected Base() { } // no parameters - aka parameterless 
    } 

    class Derived : Base { 
     // OK - implicitly calls accessible parameterless constructor base() 
     public Derived() {} 
    } 

Przykład 4 - FAIL - prywatny nie jest dostępny

class Base { 
     // "private" so it's NOT accessible by derived class 
     private Base() { } // no parameters - aka parameterless 
    } 

    class Derived : Base { 
     // FAIL - tries to implicitly call parameterless constructor base() 
     // ERROR CS0122 - Base.Base() is inaccessible due to it's protection level 
     public Derived() { } 
    } 

Przykład 5 - FAIL - Zawsze stara się wywołać konstruktora bez parametrów

class Base { 
     // "private" so it's NOT accessible by derived class 
     private Base() { } // no parameters - aka parameterless 

     // "protected" so it's accessible by derived class 
     protected Base(int a) { } // has parameter - aka NOT parameterless 
    } 

    class Derived : Base { 
     // FAIL - STILL tries to implicitly call parameterless constructor base() 
     // ERROR CS0122 - Base.Base() is inaccessible due to it's protection level 
     public Derived() { } 
    } 

Przykład 6 - NIEPOWODZENIE - Chyba, że ​​nie istnieje, wówczas zakłada wywołanie innego

class Base 
    { 
     // notice there is not parameterless constructor 
     // just one constructor does does have parameters 

     // "protected" so it's accessible by derived class 
     protected Base(int a) { } // has parameter - aka NOT parameterless 
    } 

    class Derived : Base 
    { 
     // FAIL - STILL tries to implicitly call parameterless constructor base() which doesn't exist 
     // ERROR CS7036 - There is no argument given that corresponds to the required formal parameter 'a' of Base.Base(int) 
     public Derived() { } 
    } 

Przykład 7 - OK - chyba zadzwonić samemu

class Base 
    { 
     // "private" so it's NOT accessible by derived class 
     private Base() { } // no parameters - aka parameterless 

     // "protected" so it's accessible by derived class 
     protected Base(int a) { } // has parameter - aka NOT parameterless 
    } 

    class Derived : Base 
    { 
     // OK - Explicitly calling accessible base constructor with `int` parameter 
     public Derived() 
      : base(10) 
      { } 
    } 
Powiązane problemy