6

そのタイトルは一口ですよね...

これが私がやろうとしていることです:

public interface IBar {
     void Bar();
}
public interface IFoo: IBar {
    void Foo();
}
public class FooImpl: IFoo {
    void IFoo.Foo()   { /* works as expected */ }
    //void IFoo.Bar() { /* i'd like to do this, but it doesn't compile */ }

    //so I'm forced to use this instead:
    void IBar.Bar()   { /* this would compile */ }
}

これに関する私の問題は... Bar() を呼び出すのが不便だということです:

IFoo myFoo = new FooImpl();
//myFoo.Bar(); /* doesn't compile */
((IBar)myFoo).Bar(); /* works, but it's not necessarily obvious 
                        that FooImpl is also an IBar */

IFoo.Bar(){...}だから...基本的に2つのインターフェースを1つにマージする以外に、私のクラスで宣言する方法はありますか?

そうでない場合、なぜですか?

4

6 に答える 6

5

インターフェイスで new キーワードを使用して、それが拡張するインターフェイスで宣言されたメンバーを明示的に非表示にすることができます。

public interface IBar
{
    void Bar();
}

public interface IFoo:IBar
{
    void Foo();
    new void Bar();
}

public class Class1 : IFoo
{
    void Bar(){}

    void IFoo.Foo(){}

    void IFoo.Bar(){}

    void IBar.Bar(){}
}
于 2010-12-21T16:35:25.843 に答える
1

の 2 つの実装はありませんIFoo。あなたは1つしか持っていません。
CLR は、インターフェイス ツリーの異なるポイントからのインターフェイスのコピーを区別しません。

IFoo.Bar()特に、 ;を呼び出す方法はありません。のみ呼び出すことができますIBar.Bar。別のメソッドを に
追加すると、コードが機能します。Bar()IFoo

于 2010-12-21T16:20:56.017 に答える
1

IFoo は Ibar を拡張void IFoo.Bar()してvoid IBar.Bar()いるため、まったく同じ機能です。同じメソッドを 2 回定義することはできないため、機能しません。

于 2010-12-21T16:21:45.283 に答える
1

これは、明示的に実装されたインターフェイス メソッドの単なるコンパイラ規則です。次のように記述できます。

public class FooImpl : IFoo {
    public void Foo() { /* implements IFoo.Foo */ }
    public void Bar() { /* implements IBar.Bar */ }
}

ただし、明示的な実装を使用する場合、コンパイラは、メソッドを宣言したインターフェイスの識別子名を使用することを要求します。これは理にかなっていますが、IFoo は Bar() メソッドを持つこともできます。

于 2010-12-21T16:54:22.170 に答える
1

どんな振る舞いをしたいですか?呼び出すたびIFoo.Bar()に IBar の定義を使用します。これは単なるインターフェイスであり、個別の概念がまったくないためBar()です。newキーワードを使用してスーパークラスにキャストする場合にのみ、別のメソッドを呼び出すことができます。これは、インターフェイスを実装するのではなく、クラス内のメソッドをオーバーライドするときです。

インターフェイスが互いに継承する場合、サブインターフェイスにはメソッドの所有権の概念がほとんどありません。サブインターフェイスに両方のメソッドが宣言されているかのようです。


注意: 過剰な合併症と脳のメルトダウンの可能性!!! 注意して読んでください!!!

これは許可されていると思います。間違っている場合は修正してください。

public class IBar {
     virtual void Bar() {
         //IBar implementation of Bar
     }
}
public class IFoo: IBar {
    new virtual void Foo() {
        //implementation of Foo when currently casted to IFoo
    }
}
public class FooImpl: IFoo {
    new void Foo()   { /* implementation of Foo when cast to FooImpl */ }
    new void Bar()   { /* implementation of Bar when cast to FooImpl */ }
}

わかりやすくするためにクラス名の前に I を残しましたが、インターフェイスはもうありません。呼び出されるメソッドは、オブジェクトがキャストされたクラスによって異なります。

IBar b = new IBar();
b.Bar(); //calls IBar.Bar

IFoo f = new IFoo();
f.Bar(); //calls IFoo.Bar
f.Foo(); //calls IFoo.Foo
IBar fooAsBar = (IBar) f;
fooAsBar.Bar(); //calls IBar.Bar

FooImpl fi = new FooImpl();
fi.Bar(); //calls FooImpl.Bar
fi.Foo(); //calls FooImpl.Foo 
IFoo fooImplAsFoo = (IFoo) fi;
fooImplAsFoo.Bar(); //calls IFoo.Bar
fooImplAsFoo.Foo(); //calls IFoo.Foo
IBar fooImplAsBar = (IBar) fi;
fooImplAsBar.Bar(); //calls IBar.Bar

ああ、ネストされたインターフェイスを使用していません。それらは互いに継承しているだけです。ネストされたインターフェースは次のようになります。

interface IBar {
    void Bar();

    interface IFoo {
        void Foo();
    }
}

ご覧のとおり、これはまったく異なります。2 つのインターフェイスの関係は、一方が他方の内部でのみ使用できるということだけです。それらは複雑でややトリッキーなトピックです。詳しくはこちらをご覧ください。:D

于 2010-12-21T16:23:39.077 に答える
0

私も以前これに不満を感じていましたが、重要なのは、定義上、「明示的な」実装であるという事実にあると思います。オブジェクトを IBar にキャストしない限り、Bar メソッドの呼び出しは、オブジェクトが最終的に IBar を実装するという事実に暗黙的に依存しています。

以下の例を、あなたが望むものの論理的な結論と考えてください。理論的には、FooImpl は IFoo を実装することで Bar を明示的に実装でき、理論的には、派生クラス (FooChild) は FooImpl から継承することで IBar を実装できます。問題は、これにより、(少なくとも) 2 つの異なるあいまいな「明示的な」実装パスの可能性が開かれることです。

public interface IBar {      void Bar(); } 
public interface IFoo: IBar {     void Foo(); }
public class FooImpl: IFoo {  
   void IFoo.Foo()   {  }     
   void IFoo.Bar()   { /* hypothetically, let's suppose this works */ }
   void IBar.Bar()   { /* this could then co-exist with the above.. */  } 
} 
public class FooChild : FooImpl
{
}

public class Owner
{
    public void Stuff()
    {
        FooChild child = new FooChild();
        // This invokes the "explicit" bar method (except not really...)
        ((FooImpl)child).Bar();     // Which version of Bar should be called here?
    }
}
于 2011-01-04T15:43:01.927 に答える