如果我有一个班级A
,以及从B
继承的班级C
,D
和A
,有没有办法写一个A
中的方法,当在子类上调用时,它将具有子类的返回类型?
所以,如果我要A.myMethod()
,我会得到A
,如果我要做B.myMethod()
,我会得到B
的实例?< / p>
答案 0 :(得分:2)
您所要求的并不是严格的多态性,因为您要覆盖返回类型,因此具有与原始方法不同的签名。真正的多态性不会改变这个签名,因此您所要求的并不是C#中的第一类情况。
话虽如此,至少有两种方法。
最简单的方法是覆盖该方法,使用new
关键字隐藏原始方法,允许您更改签名。
public new B MyMethod() { return (B)(base.MyMethod()); }
这将允许B
的任何用法返回B
,但实际上不会覆盖A.MyMethod
的行为。避免在代码中重复进行类型转换可能很有用。
如果你还需要覆盖方法以允许它返回类型为B
的对象,则这不能在同一个类中共存,因为编译器看到相同的签名(相同的名称,相同的参数,即使返回类型明显不同。)
第二种方式称为静态多态性,如果您正在使用某种工厂,它非常有用,但是要解决这个问题可能非常棘手,因为它只允许一个级别的实际的继承。静态多态类型以具有受其自身约束的通用组件的类型开始:
public class A<TSelf> where TSelf : A<TSelf> { }
public class B : A<B> { }
这意味着你的方法可以返回类型为TSelf
的n对象,即使这是一个抽象方法,所以每个继承者都必须处理构造函数,但是从B
继承的任何类都有一个更难的时候覆盖它,因为它继承自A<B>
,而不是A<C>
答案 1 :(得分:0)
假设您只想在myMethod
中声明方法A
,您可以执行以下操作:
namespace Test
{
class Program
{
static void Main(string[] args)
{
var a = new A();
var b = new B();
Console.WriteLine(a.M());
Console.WriteLine(b.M());
}
}
class A
{
public A M()
{
return (A)Activator.CreateInstance(GetType());
}
}
class B : A
{
}
}
打印:
Test.A
Test.B
答案 2 :(得分:0)
你所说的是基本工厂方法/模式。它有点偏离,因为创建自己的实例很奇怪。
但是可以肯定的是,你可以这样写:
class A
{
public virtual A Create()
{
return new A();
}
}
class B
{
public override A Create()
{
return new B();
}
}
当然,返回类型必须保留为基类,但由于您正在利用多态性,因此不应该成为问题。
通常,工厂方法将在另一个专用类中,只是你知道。
答案 3 :(得分:0)
是和否。考虑:
public class Parent
{
public int MyProperty { get; set; }
public virtual Parent MyMethod()
{
return new Parent();
}
}
public class A : Parent
{
public override Parent MyMethod()
{
return new A();
}
}
在A中,虽然返回类型是Parent,但您将返回A。
答案 4 :(得分:0)
如果您询问编译时间,则不能使用不同的返回类型编写覆盖方法。
但是在运行时是的,你可以,你将拥有这些类型的实例,但你必须编写你的代码,以便返回类型为&#39; A&#39;然后将它们转换为想要的类型。