[英]Multiple explicit interface implementation
我有以下基本界面
public interface IBaseAction
{
bool CanAct(...)
}
和两个继承接口说
public interface IAction1 : IBaseAction{}
和
public interface IAction2 : IBaseAction{}
我的问题是,我有一个实现这两者的类,我想实现不同的CanAct。
public class ComplexAction : IAction1, IAction2
{
bool IAction1.CanAct(...){} //doesn't compile as CanAct is not a member of IAction1!!
}
ComplexAction c=new ComplexAction();
var a1 = (IAction1)c;
var a2 = (IAction2)c;
a1.CanSave(); //THESE TWO CALLS SHOULD BE IMPLEMENTED DIFFERENTLY
a2.CanSave();
有一个相当干净的方式来做到这一点?
(另外,我的界面具有语义和至少三个功能,因此抛弃整个层次结构是不可能的,但是我愿意将bool CanAct复制到每个继承接口,如果这是唯一的解决方案(其中有4-6个))
你不能做你描述的。 试想一下,如果客户端请求IBaseAction
接口会发生什么。 应归还哪一个?
听起来我觉得每个动作应该由不同的对象实现。
您正在尝试使用Interfaces实现钻石继承。 你不允许首先实现多个类的全部原因是避免钻石继承。
如果要将两个接口组合在一起作为ComplexAction
,您可以执行以下操作:
interface IAct
{
bool CanAct();
}
class Act1 : IAct
{
public bool CanAct()
{
return true;
}
}
class Act2 : IAct
{
public bool CanAct()
{
return false;
}
}
class ComplexAction : IAct
{
private Act1 action1;
private Act2 action2;
public ComplexAction(Act1 action1, Act2 action2)
{
this.action1 = action1;
this.action2 = action2;
}
public bool CanAct()
{
return action1.CanAct() && action2.CanAct();
}
}
ComplexAction
是不同IAct
的组合。 如果你在接口名称上附加一个数字,那么你做错了什么的可能性很高。
相反,如果您希望基于接口定义不同的行为,那么接口必须在其自身上定义它的方法。
interface IAct1
{
bool CanAct();
}
interface IAct2
{
bool CanAct();
}
class SometimesAct1SometimesAct2 : IAct, IAct1, IAct2
{
bool IAct1.CanAct()
{
return false;
}
bool IAct2.CanAct()
{
return true;
}
public bool CanAct()
{
Console.WriteLine("Called on IAct or SometimesAct1SometimesAct2");
return false;
}
}
为了避免钻石继承的问题,您必须为定义特定方法的所有接口提供实现,因此不存在歧义。
我认为你正试图将继承用于不应该做的事情。 如果你有一个复杂的动作,它由更简单的动作组成 ,它不是同时有多个不同的动作。
你ComplexAction
应该有属性Action1
和Action2
类型, IAction1
和IAction2
已正确实施CanSave()
它不是由IAction1
定义的,而是由IBaseAction
定义的。
解决方案是不要让复杂的操作同时实现(您当前的解决方案可能会破坏SRP)
您需要在需要延迟的接口上重新声明IBaseAction
的成员,但是如果没有成员的隐式实现,您还需要隐式或显式地实现IBaseAction
的成员(以确保所有接口都满足)。
interface IBase {
void Act();
}
interface IAction1 : IBase {
void Act();
}
interface IAction2 : IBase {
void Act();
}
class MyClass : IAction1, IAction2 {
public void Act() {
Console.WriteLine( "satisfies IBase.Act()" );
}
void IAction1.Act() {
Console.WriteLine( "IAction1.Act()" );
}
void IAction2.Act() {
Console.WriteLine( "IAction2.Act()" );
}
static void Main( string[] args ) {
MyClass cls = new MyClass();
cls.Act();
IAction1 a = cls;
a.Act();
IAction2 b = cls;
b.Act();
Console.ReadKey();
}
}
可能有点多余的是指出,这种设计很难让重叠命名的成员强迫你像这样跳过箍,但我想我还是会注意到它。
你确实说过你不能抛弃当前的层次结构,但有可能重构它以避免这些恶作剧。
这不行。 您假设IAction1继承了IBaseAction,但事实并非如此。 接口不能继承其他接口。 您可以使用反射来查看IAction1的基类。 它不会是IActionBase。
你对你的代码所说的是:当一个类实现IAction1时,它也需要实现IBaseAction。 C#将通过假设您通过告诉它实现IAction1来实现IActionBase来帮助您。 此外,当使用IAction1类型的变量时,您可以从IBaseAction调用成员,因为它知道它已实现。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.