我很难解释为什么我要做的事情即将告诉你,但他们有理由这样留在我身边。 (建议欢迎)。
我有一个Functor,它在输入时调用一个方法。
!请注意!仿函数实际上是一种扩展方法,因此必须进行打字推断。
另外,我有一个带有2个子节点的抽象类和一个需要方法签名的接口。
示例代码如下所示:
result.next()
每当我调用Run()时,结果就是错误被推向屏幕。 我可以做些什么来强制执行我在父类中执行该方法的函子。
Functor永远不会收到A的实例,因为A是抽象的(我的意思是纯A,不是A的孩子)
其他信息:
public sealed class AbstractionTester
{
internal static void Run()
{
// The functor here accepts A type but in my original code its just a generic type.
// I wanted to keep it simple for this example only
Func<A, bool> func = a =>
{
a.CallMe(); //Displays "Error"
return true;
};
B obj = new B();
func(obj);
}
}
internal interface ICallMe<T>
where T : MyEntity
{
T CallMe();
}
//Just a class which holds data I would like to store about every object I have, for example: CreateDate
internal abstract class MyEntity
{ }
internal abstract class A : MyEntity, ICallMe<A>
{
//some other fields i would like to store..
// This method here must never be invoked
public A CallMe()
{
//throw new Exception();
Console.WriteLine("Error");
return this;
}
}
internal class B : A, ICallMe<B>
{
public new B CallMe()
{
Console.WriteLine("B");
return this;
}
}
internal class C : A, ICallMe<C>
{
public new C CallMe()
{
Console.WriteLine("C");
return this;
}
}
和CallMe
中写下B
的返回类型。我无法将其更改为C
。答案 0 :(得分:1)
这实际上很奇怪。为什么不使用访客模式?
然后你可以这样做:
static void Main(string[] args)
{
Element a = new A();
Element b = new B();
Element c = new C();
ICallMe callMe = new CallMe();
a.accept(callMe);
b.accept(callMe);
c.accept(callMe);
}
以下实施:
public interface ICallMe
{
void Visit(A a);
void Visit(B b);
void Visit(C c);
}
public class CallMe : ICallMe
{
public void Visit(A c)
{
Console.WriteLine("A");
}
public void Visit(B b)
{
Console.WriteLine("B");
}
public void Visit(C a)
{
Console.WriteLine("C");
}
}
interface Element
{
void accept(ICallMe visitor);
}
public class A : Element
{
public void accept(ICallMe visitor)
{
visitor.Visit(this);
}
}
public class B : Element
{
public void accept(ICallMe visitor)
{
visitor.Visit(this);
}
}
public class C : Element
{
public void accept(ICallMe visitor)
{
visitor.Visit(this);
}
}
答案 1 :(得分:0)
这是一个无法将public A CallMe()
定义为virtual
的解决方案。这样做的好处是,子类可以将CallMe()
定义为new
,以便他们可以返回B
或C
。但是,它要求您可以创建课程public
而不是internal
(或者您将获得an error)。
使用动态分派调用实际的运行时类型而不是接口中声明的类型:
Func<A, bool> func = a => {
var runtimeType = (dynamic)a;
runtimeType.CallMe();
return true;
};
答案 2 :(得分:0)
这有一个特定的语言功能;界面重新实现。
明确重新实现界面并使通用仿函数采用ICallable<T>
:
internal class B : A, ICallMe<B>
{
B ICallable<B>.CallMe()
{
Console.WriteLine("B");
return this;
}
}
internal class C : A, ICallMe<C>
{
B ICallable<C>.CallMe()
{
Console.WriteLine("B");
return this;
}
}
你的算子应该是:
Func<T, bool> func = a => ...
并且T
应该被约束(在方法或类级别)ICallable<T>
。
更新:如果仿函数确实是扩展码,我不确定问题是什么:
public static bool MyEnxtensionMethod<T>(T argument)
where T: ICallable<T>
{
argument.CallMe();
return true;
}
为什么需要将A
保留在任何地方?
答案 3 :(得分:0)
确保永远不会调用A CallMe
方法的最佳方法是不存在。
internal abstract class MyEntity
{ }
internal abstract class A : MyEntity
{ }
现在永远不能按要求调用它。
现在使界面协变:
internal interface ICallMe<out T>
where T : MyEntity
{
T CallMe();
}
然后将Func<A, bool>
更改为Func<ICallMe<A>, bool>
public sealed class AbstractionTester
{
internal static void Run()
{
// The functor here accepts A type but in my original code its just a generic type.
// I wanted to keep it simple for this example only
Func<ICallMe<A>, bool> func = a =>
{
a.CallMe(); //Displays "B"
return true;
};
B obj = new B();
func(obj);
}
}