您已经得到了一些解释如何使用空界面执行此操作的答案:
interface IMachineSomething {}
…
var m = new List<IMachineSomething>();
如果您想将所有对象放入该列表,则此方法可以正常工作。但是,如果您想真正从列表中获取对象 怎么办?您实际上可以用它们做什么,上述解决方案会迫使您做什么?
以下显示使用非空接口可以做得更好。
IMachineSomething 是一个空接口。也就是说,如果您真的想对列表中的对象做某事,那么您将看到的只是该接口定义的空合约。所有实际功能都存在于具体的class 类型中。因此,您首先必须检查它们的类型,然后执行类型转换才能访问公共字段:
foreach (IMachineSomething sth in m)
{
if (sth is MachineLine)
{
var machineLine = (MachineLine)sth;
machineLine.DoThis();
}
else if (sth is MachineCircle)
{
var machineCircle = (MachineCircle)sth;
machineCircle.DoThat();
}
else …
}
由于您使用的是面向对象的语言,因此有一个更好的解决方案:多态性。也就是说,将通用功能(属性和方法)放在接口中,这样您在浏览列表时就不需要区分类型:
interface IMachineSomething
{
void DoSomething();
}
class MachineLine : IMachineSomething
{
…
public void DoSomething() { DoThis(); } // example for implicit implementation, or…
}
class MachineCircle : IMachineSomething
{
…
void IMachineSomething.DoSomething() { DoThat(); } // …explicit implementation
}
这使您可以摆脱 if (sth is …) 类型检查和后续类型转换,并将您的代码简化为:
foreach (IMachineSomething sth in m)
{
sth.DoSomething();
}
循环不再需要关心如何准确处理每个元素。它只需要知道它必须对元素“做某事”,元素本身就会知道这意味着什么。
另见: