C# 继承-调用子方法而不是父方法
这将很难解释为什么我要做的事情我要告诉你,但他们有一个原因,所以留在这里和我在一起。(欢迎提出建议) 我有一个函子,它在输入时调用一个方法 !请注意函子实际上是一个扩展方法,因此必须有类型推断 另外,我有一个带有2个child的抽象类和一个需要方法签名的接口 示例代码如下所示:C# 继承-调用子方法而不是父方法,c#,oop,inheritance,abstract-class,abstract,C#,Oop,Inheritance,Abstract Class,Abstract,这将很难解释为什么我要做的事情我要告诉你,但他们有一个原因,所以留在这里和我在一起。(欢迎提出建议) 我有一个函子,它在输入时调用一个方法 !请注意函子实际上是一个扩展方法,因此必须有类型推断 另外,我有一个带有2个child的抽象类和一个需要方法签名的接口 示例代码如下所示: public sealed class AbstractionTester { internal static void Run() { // The functor here accep
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;
}
}
公共密封类抽象测试仪
{
内部静态无效运行()
{
//这里的函子接受一个类型,但在我的原始代码中它只是一个泛型类型。
//我只想对这个例子保持简单
Func Func=a=>
{
a、 CallMe();//显示“错误”
返回true;
};
B obj=新的B();
func(obj);
}
}
内部接口ICallMe
T:MyEntity在哪里
{
T叫我();
}
//只是一个类,它保存我想要存储的关于我拥有的每个对象的数据,例如:CreateDate
内部抽象类MyEntity
{ }
内部抽象类A:MyEntity,ICallMe
{
//其他一些我想存储的字段。。
//这里的方法不能被调用
公共电话号码()
{
//抛出新异常();
控制台写入线(“错误”);
归还这个;
}
}
内部B类:A,ICallMe
{
公共新B CallMe()
{
控制台。写入线(“B”);
归还这个;
}
}
内部C类:A,ICallMe
{
公共新C CallMe()
{
控制台。写入线(“C”);
归还这个;
}
}
每次我调用Run()时,结果是错误会显示在屏幕上。
我可以做些什么来强制我拥有的这个函子不会在父类中执行该方法
函子无论如何都不会收到A的实例,因为A是抽象的(我指的是纯A,而不是A的子)
其他信息:
- 我必须在类
和B
中明确写出C
的返回类型。我无法将它们更改为类型CallMe
A
- 我需要在函子中保留A(或类似的东西)的类型,因为我需要为某些代码延续推断类型
- 这里有一个解决方案,它不需要将
公共调用定义为虚拟。这样做的好处是,子类可以将其CallMe()
定义为new
,以便返回B
或C
。但它要求您可以将类设置为public
,而不是internal
(否则您将获得)
使用动态调度调用实际运行时类型,而不是在接口中声明的类型:
Func<A, bool> func = a => {
var runtimeType = (dynamic)a;
runtimeType.CallMe();
return true;
};
Func这有一个特定的语言特性;接口重新实现
显式重新实现接口,并使泛型函子具有可调用的iCalable
:
为什么需要将A
保留在任何地方?确保A的CallMe
方法从不被调用的最佳方法是使其不存在
现在,它永远无法根据需要调用
现在,使接口协变:
internal interface ICallMe<out T>
where T : MyEntity
{
T CallMe();
}
内部接口ICallMe
T:MyEntity在哪里
{
T叫我();
}
然后将Func
更改为Func
公共密封类抽象测试仪
{
内部静态无效运行()
{
//这里的函子接受一个类型,但在我的原始代码中它只是一个泛型类型。
//我只想对这个例子保持简单
Func Func=a=>
{
a、 CallMe();//显示“B”
返回true;
};
B obj=新的B();
func(obj);
}
}
这真是一个奇怪的实现。为什么不使用访客模式
然后你可以做:
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);
}
}
为什么不在A的B类方法中重写
,而是使用新建
?@Tigran,因为方法CallMe是在接口中定义的。如何实现相同的通用接口两次?只有返回类型不同吗?@JeroenvanLangen我在哪里说过我两次执行泛型交互?如果您指的是functor参数类型,那么它将推断该类型,因为在我的代码中,functor实际上是一个扩展方法。如果你提到我写ICallMe的事实,这个例子就最小化了,在我的原始代码中,我几乎在我所有的类上都使用它。它在这里:内部抽象类A:MyEntity,ICallMe
和这里内部类B:A,ICallMe
所以:ICallMe
和ICallMe
,这就是问题所在。它们使用不同的返回类型强制实现2个方法。不能定义只在返回类型上不同的相同methodname。(重载问题)如果您从T CallMe()更改返回类型
到void CallMe(out T)
它会起作用。除非绝对需要,否则我宁愿不使用铸造。对不起,我想到的唯一其他方法是使用虚拟
,它不符合您的要求:(我不想在functor的参数和iCalable之间设置约束。我需要确定其中的类型。如果您仔细阅读我的帖子,我提到functor实际上是一个扩展方法,所以我需要将类型a保留在那里。@OriRefael那么您如何考虑将其设置为泛型(正如您在问题中指出的那样)如果您不以某种方式约束泛型类型以便编译器知道调用是安全的,则调用CallMe()
。@oriefeal您的扩展方法的签名是什么?如果您不发布相关代码,则很难给出答案。实际上,我在最后选择了动态调度,但我可能会将其更改为访问者模式(我在写动态调度时也想到了这一点)它似乎就是解决方案。
internal abstract class MyEntity
{ }
internal abstract class A : MyEntity
{ }
internal interface ICallMe<out T>
where T : MyEntity
{
T CallMe();
}
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);
}
}
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);
}
}