将接口强制转换为它不继承的另一个接口
本文关键字:接口 继承 另一个 转换 | 更新日期: 2023-09-27 18:32:52
我希望这里有人能解释我所做的错误假设。在 C# 4.0 中,我有 2 个接口和一个实现这两个接口的类。在方法中,我声明了一个具有第一个接口类型的变量,使用实现两个接口的类实例化它,并且可以以某种方式将其成功强制转换为第二个接口,如以下代码所示:
public interface IFirstInterface
{
void Method1();
}
public interface ISecondInterface
{
void Method2();
}
public class InterfaceImplementation : IFirstInterface, ISecondInterface
{
public void Method1() { }
public void Method2() { }
}
public class SomeClass
{
public void SomeMethod()
{
IFirstInterface first = new InterfaceImplementation();
first.Method1();
// Shouldn't the next line return null?
ISecondInterface second = first as ISecondInterface;
// second is not null and the call to Method2() works fine
second.Method2();
}
}
我试图理解为什么选角成功。是的,该类实现了这两个接口,但我认为由于第一个变量被声明为 IFirstInterface(它不继承自 ISecondInterface),因此转换仍然应该失败。
我也尝试过用其他方式重组我的代码,比如不使用"as",但强制转换仍然成功。
我错过了什么?
从您的示例中,您应该在调用任何功能之前测试类型类型。第一次创建将创建一个完全限定的"接口实现",支持这两个接口。 但是,您将其放入仅第一个接口的声明类型中。 因此,从"第一个"对象的角度来看,它只关心与 IFirstInterface 实现相关的任何内容。
现在,接下来是你...即使您已经创建了对象,您仍然可以询问...顺便一提。。。您也是第二界面吗? 如果是这样,请执行此操作...
IFirstInterface first = new InterfaceImplementation();
if( first is ISecondInterface )
// typecast since the second interface is legit, then call it's method 2
((ISecondInterface)first).Method2();
实例的实际类型first
指向实现这两个接口。因此,显然Method1
和Method2
都可以在对象上使用。
first
的静态类型仅允许您访问Method1
。second
的静态类型仅允许您访问Method2
。我使用任一接口声明对对象的引用,您只需选择将实例视为履行所选合约(接口)的对象。
由于InterfaceImplementation
实现了这两个接口,因此您可以选择使用任一接口引用实例。
如果你从具体对象的角度来看,你可以说"我是一个IFirstInterface,但我也是一个ISecondInterface"。这是你的意思吗?您描述的问题最终会在继承/实现链中转换。
你唯一缺少的是,这正是它的意思,这是一个有用的功能,而不是问题。 在强制转换时,你可以将代码基本上想象成说,"我不在乎我知道这个对象的类型是什么,我想看看它是否可以转换为类型 T"。 在这种情况下,由于底层对象是 InterfaceImplementation
型 ,无论它目前被称为 IFirstInterface
,答案是肯定的,它可以转换为ISecondInterface
。
欢迎来到多态性。对象first
始终是 InterfaceImplementation 的实例。您选择引用它的方式不会影响对象的真正"是什么"。这就是抽象概念作为一个整体的工作方式。
这确实表明存在设计缺陷。 客户端知道这两个接口是由同一个对象实现的。 对于您的示例,这很好,但如果这些接口是单独实现的,您将无法从第一个跳转到第二个接口。理想情况下,最好有某种查询接口,您可以在其中从一种类型转到另一种类型。