C# 当用接口隐藏类时,重写的实现是否仍然存在?
我有C# 当用接口隐藏类时,重写的实现是否仍然存在?,c#,selenium-webdriver,C#,Selenium Webdriver,我有IWebElement界面。它需要实现Click()方法。因此,WebDriver库中的某些方法返回实现的IWebElement 我有自己的接口IPageElement:IWebElement和一个具体的类PageElement,它实现了Click()方法不同(一些等待和异常处理) 假设我有两种方法: IPageElement GetSomething() => new PageElement(); IWebElement GetSomethingElse() => new Pa
IWebElement
界面。它需要实现Click()
方法。因此,WebDriver库中的某些方法返回实现的IWebElement
我有自己的接口IPageElement:IWebElement
和一个具体的类PageElement
,它实现了Click()代码>方法不同(一些等待和异常处理)
假设我有两种方法:
IPageElement GetSomething() => new PageElement();
IWebElement GetSomethingElse() => new PageElement();
据我所知,结果将被削减,只保留接口成员。但是我会保留被覆盖的Click()在这两种情况下,代码>从PageElement
实现?是。IPageElement的任何实现都必须同时实现Click()和GetSomething()方法,以便这些方法在IPageElement的任何结果实现中都可用。如果将相同的实现分配给IWebElement,则只有click方法可用,因为IWebElement没有定义GetSomething
public interface IWebElement
{
void Click();
}
public interface IPageElement : IWebElement
{
void GetSomething();
}
public class PageElementImpl : IPageElement
{
public void Click()
{
Console.WriteLine("Click");
}
public void GetSomething()
{
Console.WriteLine("GetSomething");
}
}
static void Main(string[] args)
{
IWebElement webElement = new PageElementImpl();
IPageElement pageElement = new PageElementImpl();
webElement.Click(); //Legal
pageElement.Click(); //Legal
webElement.GetSomething(); //Not Legal as GetSomething() is not part of IWebElment
pageElement.GetSomething(); //Legal
}
让我们编写一些代码
interface IW
{
void C();
}
interface IP : IW
{
void D();
}
class W : IW
{
public virtual void C() { Console.WriteLine("WC"); }
}
class P : W, IP
{
public override void C() { Console.WriteLine("PC"); }
public virtual void D() { Console.WriteLine("PD"); }
}
...
IP ip = new P();
ip.C(); // PC
IW iw = new P();
ip.C(); // PC
在这两种情况下,覆盖实现都会获胜
但是,它是一个压倒一切的实现,这一点非常重要。C#中有一条非常微妙且经常被误解的规则。考虑这种情况:
class W2 : IW
{
public void C() { Console.WriteLine("W2C"); } // NOT VIRTUAL
}
class P2 : W2, IP
{
public new void C() { Console.WriteLine("P2C"); }
public virtual void D() { Console.WriteLine("P2D"); }
}
这里发生了什么
IP ip = new P2();
ip.C();
IW iw = new P2();
ip.C();
同样,我们两次都得到P2C。所以一切看起来都很好,即使“覆盖”是非虚拟化的过载,对吗
那么当我们这样做的时候会发生什么呢
class P3 : P2
{
public new void C() { Console.WriteLine("P3C"); }
}
...
IP ip = new P3();
ip.C();
IW iw = new P3();
ip.C();
我们两次仍然得到P2C。这可能令人惊讶!非虚拟重写重载方法不会更新此处的接口实现,但在上一个示例中更新了!为什么呢
如果您这样做:
class P4 : P2, IP // NOTE IP
{
public new void C() { Console.WriteLine("P4C"); }
}
...
IP ip = new P4();
ip.C();
IW iw = new P4();
ip.C();
然后我们打印出P4C
C#中的规则是,当继承列表中提到接口时,编译器决定哪个方法槽与哪个接口成员相关联。这是P3和P4之间唯一密切相关的区别
这在C#中被称为“接口重新实现规则”,这相当棘手。如果要将非虚拟方法与接口重新实现和继承混合使用,请务必小心。当您尝试对从GetSomething
和GetSomethingElse
返回的任何对象运行click方法时,会发生什么情况?接口没有实现,因此PageElement中的非实现将“覆盖”任何现有的logic@ChetanRanpariya,它可能会以某种方式点击它。由于检查实现需要一个异常,而且我在测试项目中没有可以轻松使用的控制台来附加控制台。WriteLine
测试实际使用的实现并不是那么简单。您确实有一个浏览器,所以可以在这里尝试。创建一些类和接口,看看会发生什么。这比在上面发布原始问题要省力。试试Igor的建议。这会消除你的疑虑。即使在那之后,你有任何困惑,欢迎回到这里。