2016-07-19 5 views
6

Joseph AlbahariとBen Albahari(O'Reilly)の「C#6.0 in a Nutshell」。派生クラスのコンストラクタは、ベースキーワードを使用する必要がありますか?

Copyright 2016 Joseph AlbahariとBen Albahari、978-1-491-92706-9。

状態パラメータなし基本クラスのコンストラクタの暗黙の呼び出しを導入した後、96ページで次のように:

基底クラスが全くアクセスパラメータなしのコンストラクタを持っていない場合は、サブクラスはbaseキーワードを使用することを余儀なくされています彼らのコンストラクタで。

これを裏付けるためにコードスニペットを作成しようとしていますが、まだ成功していません。

マイスニペット:

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(); 
} 

私は本の肯定以下、コンパイラエラーを取得することが期待が、私は何を取得していません。コードが実行され、正しく表示されます。

私の質問は:のサブクラスでは、基本キーワードを強制的に使用しているとはどういう意味ですか?私はそのようなシナリオを再現しようとしています。

私には何が欠けていますか?

答えて

10

Yは、基底クラス、Xのためのパラメータなしのコンストラクタへのアクセス権を持っていないクラスを使用してDervivedクラスのコンストラクタから別のコンストラクタを呼び出すことを余儀なくしていることクラスはコンストラクタを定義しません。暗黙的なパラメータのないコンストラクタがあります。

あなたが書く場合:

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

を次にもはやYXのアクセスパラメータなしのコンストラクタはありません。

+0

しかし、これは、サブクラスがベースキーワード*を使用するように強制されるケースをどのように指摘していますか? – Veverke

+3

@Veverke - そのコンストラクタを 'X'クラスに追加しようとしましたか?その場合は、コンパイルエラーが発生しているはずです。 –

+0

@Damien_The_Unbeliever:このようなコンストラクタを追加すると、現在のYコンストラクタをinパラメータを受け取るように変更するか、パラメータのないコンストラクタをXに追加するように強制します。または、Yの現在の値にbase(0)コンストラクタ。最後のケースでは、あなたが持っていないパラメータを必要とするコンストラクタを呼び出すことはあまり意味がありませんが、ベースキーワード*(これは唯一疑問点です)を使用することを余儀なくされました。 3の少なくともこの第3のシナリオでは、基本キーワード**の使用が強制されています。 – Veverke

5

問題は、サンプルコードを誤解していることに起因します。 コンストラクタをclass Xに定義していないため、C#で暗黙的に定義されています。この暗黙のコンストラクタは、引数なしのコンストラクタです。

あなたが言及している見積もりは、デフォルトではないコンストラクタを実際に作成した場合を指します。

デフォルト以外のコンストラクタを記述すると、暗黙的なコンストラクタの生成が抑制されます。これは、あなたがもしあるため、明示的にbaseキーワード

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

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

自分1を呼び出さない限り、これが質問に答えていません。私は基本的なキーワード*を使用することによって本が何を意味するのかを尋ねる。 – Veverke

+1

パラメータを持たないコンストラクタを作成する必要はありません。 – Servy

+0

@Servy良い点。私の答えは –

0

同じルール、

...除いてこれは実際に部材基底クラスの他のメンバーにアクセスするための通常のルールよりも違いはありません。

コンストラクタは、通常の関数ではありません。

主な違いは、派生クラスが自動的に基本コンストラクタを呼び出すことです。具体的には、パラメータを取らない基本コンストラクタです。

コンストラクタが存在しない場合、エラーが発生します。存在してもアクセス権がない場合は、エラーが発生します。

基本クラスに対してコンストラクタをまったく指定しない場合、そのクラスは何もしないパラメータのないコンストラクタを持つとみなされます。

コンストラクタを暗黙的に作成して指定しないと、別の方法で記述します。 - OK - 暗黙のデフォルト空のコンストラクタ

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() { } 
    } 

例2 - OK - バリアフリーベース

例3:ここでは

は、あなたがこの問題に直面することはありませんでしょうときの7例がありますコンストラクタ

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() {} 
    } 

例3 - OK - FAIL - - FAIL - - 常にパラメータなしのコンストラクタ

を呼び出そうとしたプライベート

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() { } 
    } 

例5にアクセスできないまだアクセス

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() {} 
    } 

例4は、保護された手段は、

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() { } } 

例6 - FAIL - それが存在しない場合を除き、その後、実施例7他の

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() { } 
    } 

を呼び出すことを前提と - OK - あなたは

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) 
      { } 
    } 
関連する問題