2009-07-09 14 views
3

次の例を考えてみましょう。私はインターフェイスMyInterfaceと2つの抽象クラスMyAbstractClass1とMyAbstractClass2を持っています。 MyAbstractClass1はMyInterfaceを実装しますが、MyAbstractClass2は実装しません。インターフェイスを実装する抽象クラスの理解に役立つ必要があります

私は3つの具体的なクラスを持っています。

  1. MyConcreteClass1はMyAbstractClass1から派生していますが、MyInterfaceは実装していません。
  2. MyConcreteClass2はMyAbstractClass2から派生していますが、MyInterfaceを実装しています。
  3. MyConcreteClass3はMyAbstractClass1から派生し、MyInterfaceを実装しています。

ConcreteClass1は、MyAbstractClass1から派生しているため、暗黙的にMyInterfaceを実装していますか? MyAbstractClass1が暗黙的にMyIntefaceのメソッドを実装すると仮定すると、ConcreteClass1はMyIntefaceメソッドにアクセスするためにMyInterfaceにキャストする必要はありません。

MyAbstractClass1は、暗黙的にMyInterfaceのメソッドを抽象メソッドとして実装できますが、明示的にMyInterfaceのメソッドを抽象メソッドとして実装することはできません。どうしてこれなの?

MyConcreteClass3は、その基本クラスによって既に実装されているインターフェイスを実装しているため、過剰ですか? MyAbstractClass1から派生するすべてのクラスがMyInterfaceも実装する必要があることを知っていたとしても、それをやりたい理由がありますか?ここ

はクラス図

alt text http://files.getdropbox.com/u/113068/abstractclassesandinterfaces.png

は、ここでは、コード情報は:この場合

//interface 
public interface MyInterface 
{ 
    void MyMethodA(); 
    void MyMethodB(); 
    void MyMethodC(); 

} 

//abstract classes 
public abstract class MyAbstractClass1 : MyInterface 
{ 
    public void MyMethodA() 
    { 
    } 


    void MyInterface.MyMethodB() 
    { 

    } 

    //Error: "the modifier abstract is not valid for this item" 
    //abstract void MyInterface.MyMethodC(); 

    //This works 
    public abstract void MyMethodC(); 

    public abstract void MyMethodZ(); 

} 


public abstract class MyAbstractClass2 
{ 
    public void MyMethodX() 
    { 
    } 

    public abstract void MyMethodY(); 

} 

//Concrete classes 
//ConcreteClass 1: Only Abstract class implements the interface 
public class ConcreteClass1 : MyAbstractClass1 
{ 
    public override void MyMethodC() 
    { 
    } 

    public override void MyMethodZ() 
    { 

    } 
} 

//ConcreteClass 1: Only Concrete class implements the interface 
public class ConcreteClass2 : MyAbstractClass2, MyInterface 
{ 
    public override void MyMethodY() 
    { 
    } 

    public void MyMethodA() 
    { 

    } 

    public void MyMethodB() 
    { 

    } 

    public void MyMethodC() 
    { 

    } 

} 
//ConcreteClass 1: Both concrete and abstract class implement the interface 
public class ConcreteClass3 : MyAbstractClass1, MyInterface 
{ 
    public override void MyMethodC() 
    { 

    } 

    public override void MyMethodZ() 
    { 

    } 
} 

答えて

3

ConcreteClass1はMyAbstractClass1から派生しているため、MyInterfaceも暗黙的に実装していますか?

はい。

MyIntefaceメソッドにアクセスするには、ConcreteClass1をMyInterfaceにキャストする必要はありません。

正しい。 (myConcreteClass1 is MyInterface)trueと評価されます。

MyAbstractClass1は、暗黙的にMyInterfaceのメソッドを抽象メソッドとして実装できますが、明示的にMyInterfaceのメソッドを抽象メソッドとして実装することはできません。

明示的な実装は、重複しているメンバーの署名を区別することです。明示的な実装は、実装しているクラスに対してプライベートなので、派生クラスからはアクセスできません(したがって、抽象クラスにはできません)。また、MyAbstractClass1から派生したクラスにMyInterfaceを明示的に実装するよう強制することもできないため、抽象メンバを確実に実装する方法はありません。

MyConcreteClass3は、既に基本クラスによって実装されているインターフェイスを実装しているため、過剰ですか? MyAbstractClass1から派生するすべてのクラスがMyInterfaceも実装する必要があることを知っていたとしても、それをやりたい理由がありますか?

必ずしも、あなたが明示的MyConcreteClass3上の重複メンバーと区別するためのインターフェイスのメンバーを実装する必要がある場合。それ以外の場合は不要です。

+0

"明示的な実装は、実装しているクラスのプライベートなものです":実際には、それよりもプライベートなので、直接アクセスすることはできません。最初にインターフェイスにキャストする必要があります。誰もがインターフェイスを通してそれにアクセスできるので、それは幾分公開されます。本当に奇妙な、しかし、まだ素晴らしい機能。 –

1

は、すべての3つのクラスが(直接的または間接的に)インタフェースを実装します。これは、MyAbstractClass1がMyInterfaceを実装し、MyConcreteClass1がMyAbstractClass1から派生しているため、MyConcreteClass1をMyInterfaceとして扱うことができるためです。 MyConcreteClass2は、MyInterfaceとして扱う限り、MyAbstractClass1から派生したもので扱うことができます。 MyAbstractClass1はすでにMyInterfaceを実装しているので、ConcreteClass3のMyInterfaceからの派生は少し冗長です。

これらの情報はすべて、MyInterfaceを既に実装しているMyAbstractClass1から派生しているため、MyConcreteClass3にMyInterfaceを実装するのは冗長です。 私はあなたがインターフェイスメソッドの抽象実装を持っていない理由は、それはコード自体を提供せず、それがサブカルセージでオーバーライドされることを保証できないということです。代わりにVirtualを使用してください。

+0

なぜ私はdownvoteを取得しましたか? – RCIX

+0

「ホールドオン」は悪い答えです... –

+0

そこはいいですか? – RCIX

1

冗長ではありません。あなたは派生クラスからインターフェイスを追加した場合あなたは...

Base 
Hide 
M! 
M! 

を取得します

var d = new D(); 
var i = (I)d; 
var u = new U(); 

i.A(); 
d.A(); 
u.M(d); 
u.M(i); 

... ...

これを実行
public interface I 
{ 
    void A(); 
} 

public abstract class B : I 
{ 
    public void A() 
    { 
     Console.WriteLine("Base"); 
    } 
} 

public class D : B 
{ 
    public void A() 
    { 
     Console.WriteLine("Hide"); 
    } 
} 

public class U 
{ 
    public void M(I i) 
    { 
     Console.WriteLine("M!"); 
    } 
} 

を簡素化するために、このクラスの設定を考えてみましょう...

public class D : B, I 
{ 
    public void A() 
    { 
    Console.WriteLine("Hide"); 
    } 
} 

You wil私は...

Hide 
Hide 
M! 
M! 

したがって、派生クラスのInessを取得したときに取得するインターフェイスメソッドの実装に影響します。