.NET C# 在父接口中显式实现祖父母接口方法

发布于 2024-10-09 02:01:04 字数 741 浏览 6 评论 0原文

这个标题很拗口,不是吗?...

这就是我想做的:

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 */

所以...有没有办法声明 < code>IFoo.Bar(){...} 在我的类中,除了基本上将两个接口合并为一个之外?

如果没有,为什么?

That title's a mouthful, isn't it?...

Here's what I'm trying to do:

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 */ }
}

My problem with this is that it's... inconvenient to call 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 */

So... Is there a way to declare IFoo.Bar(){...} in my class, other than basically merging the two interfaces into one?

And, if not, why?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

雪若未夕 2024-10-16 02:01:04

可以在接口中使用 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(){}
}

It's possible to use the new keyword in an interface to explicitly hide a member declared in the interface it extends:

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(){}
}
眼前雾蒙蒙 2024-10-16 02:01:04

您没有两个 IFoo 实现;你只有一个。
CLR 不区分来自接口树中不同点的接口副本。

特别是,无法调用 IFoo.Bar();您只能调用IBar.Bar
如果您向 IFoo 添加单独的 Bar() 方法,您的代码将正常工作。

You don't have two implementations of IFoo; you only have one.
The CLR does not distinguish between copies of interfaces that come from different points in the interface tree.

In particular, there is no way to call IFoo.Bar(); you can only call IBar.Bar.
If you add a separate Bar() method to IFoo, your code will work.

☆獨立☆ 2024-10-16 02:01:04

由于 IFoo 扩展了 Ibar,因此 void IFoo.Bar()void IBar.Bar() 是完全相同的函数。您不能两次定义相同的方法,这就是它不起作用的原因。

Since IFoo extends Ibar, void IFoo.Bar() and void IBar.Bar() are the exact same function. You cannot define the same method twice, that's why it doesn't work.

笑红尘 2024-10-16 02:01:04

您希望该行为是什么?每当您调用 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();
    }
}

正如你所看到的,这是完全不同的。两个接口之间的关系只是一个接口只能在另一个接口内部使用。它们是一个复杂且有些棘手的话题。您可以在此处了解更多信息。 :D

What would you want the behavior to be? Whenever you call IFoo.Bar() its going to use the definition in IBar, because its just an interface and has no separate conception of Bar() whatsoever. You can only have a different method called when casting to a superclass with the new keyword, and that's when you are overriding a method in a class, not implementing and interface.

When interfaces inherit one another, sub-interfaces have little ownership conception of a method. Its as if the sub-interface has both methods declared in it.


Caution: potential over-complication and brain meltdown!!! Read with caution!!!

I believe this is allowed, correct me if I'm wrong:

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 */ }
}

left the I's before the class name for clarity, but there are no longer any interfaces. The method that is called will depend on what class the object has been cast to.

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

Oh, and you're not using nested interfaces, they are just inheriting from one another. Nested interfaces are like this:

interface IBar {
    void Bar();

    interface IFoo {
        void Foo();
    }
}

As you can see this is completely different. The relationship between the two interfaces is only that one can only be used inside of the other. They are a complicated and somewhat tricky topic. You can read more here. :D

倥絔 2024-10-16 02:01:04

这只是显式实现的接口方法的编译器约定。你可以这样写:

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

但是如果你想使用显式实现,那么编译器坚持你使用声明该方法的接口的标识符名称。这是有道理的,IFoo 也可以有一个 Bar() 方法。

This is just a compiler convention for explicitly implemented interface methods. You could write it like this:

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

But if you want to use explicit implementation then the compiler insists you use the identifier name of the interface that declared the method. Which makes sense, IFoo could also have a Bar() method.

荆棘i 2024-10-16 02:01:04

我以前也对此感到沮丧,但我认为关键在于,根据定义,它是一个“显式”实现。除非您将对象转换为 IBar,否则对 Bar 方法的任何调用都隐式依赖于该对象最终实现 IBar 的事实。

将下面的示例视为您想要的逻辑结论。理论上,FooImpl 可以通过实现 IFoo 来显式实现 Bar,理论上,派生类(FooChild)可以通过继承 FooImpl 来实现 IBar。问题是,这开辟了(至少)两种不同的模糊“显式”实现路径的可能性:

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?
    }
}

I've been frustrated by this before, too, but I think the key lies in the fact that it is, by definition, an "explicit" implementation. Unless you're casting your object to IBar, then any invocation of the Bar method is implicitly relying on the fact that the object ultimately implements IBar.

Consider the example below as a logical conclusion to what you want. Theoretically, FooImpl could explicitly implement Bar by virtue of implementing IFoo, and theoretcially, a derived class (FooChild) could implement IBar by virtue of inheriting from FooImpl. The problem is that this opens up a possibility of (at least) two different ambigous "explicit" implementation paths:

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?
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文