在基抽象类中使用派生类型
本文关键字:派生 类型 抽象类 | 更新日期: 2023-09-27 18:20:48
好的,我有许多从基类派生的不同类。这个基类是一个包含commom方法的抽象类。
其中一个方法是Copy
方法,它应该存在于所有派生类中,所以,我把它放在基类中。但是,我希望它返回derived type
,而不是基或对象。
我得到的解决方案是使用一个类型参数:
abstract class CopyableClass<T>
{
public abstract T Copy();
}
class DerivedClass : CopyableClass<DerivedClass>
{
public override DerivedClass Copy()
{
//do what is needed for copy and return a new DerivedClass
}
}
因此,这里的主要目的是
删除基类中的类型参数,并且仍然使方法返回相应的派生类型。
一个解决方法。
到目前为止,我能做的最好的事情是下面的一条评论,但它仍然使用通用参数
abstract class BaseClass
{
//base methods not related to deriving type
}
interface ICopyable<T>
{
T Copy();
}
class DerivedClass : BaseClass, ICopyable<DerivedClass>
{
public DerivedClass Copy()
{
//do what is needed for copy and return a new DerivedClass
}
}
你真的不能。基类不可能知道未来的所有实现。您将不得不求助于一个通用抽象类(就像您所做的那样)类型或一个通用Copy
方法。
public abstract class CopyableClass
{
public abstract T Copy<T>() where T : CopyableClass;
}
public class DerivedClass : CopyableClass
{
public override T Copy<T>()
{
if(typeof(T) != typeof(DerivedClass))
throw new ArgumentException();
// return your copy
}
}
或者,如果你想在基类中推广类型检查:
public abstract class CopyableClass
{
public T Copy<T>() where T : CopyableClass
{
if(GetType() != typeof(T))
throw new ArgumentException();
return (T) Copy();
}
protected abstract CopyableClass Copy();
}
public class DerivedClass : CopyableClass
{
protected override CopyableClass Copy()
{
return // Your copy;
}
}
请注意,第二个方法对派生类的实现给予了很大的信任,因为它将盲目地强制转换抽象方法的返回值。编译器将允许您在派生类型中返回另一个实现CopyableClass的类型,但这将是一个运行时错误。如果你对所有派生实现都有绝对的控制权(即你的抽象类也有一个内部构造函数),这就不是问题。
这将允许您将这个基类设置为派生类型并返回它。
public abstract class BaseClass<TDerived> : where TDerived: BaseClass<TDerived>
{
public TDerived DoSomethingCommon(string param)
{
var derivedType = (TElement)this;
//do something.
return derivedType;
}
}
这个解决方案涉及一个中产阶级,但我认为它更符合您所寻找的。至少你可以获得隔离你的复制代码的可能好处
public abstract class BaseClass
{
}
public abstract class CopyableClass<T> : BaseClass
where T: BaseClass, new()
{
public T Copy()
{
var copy = new T(); // Creating a new instance as proof of concept
return copy;
}
}
public class DerivedClass : CopyableClass<DerivedClass>
{
}
您实际上想要在基类中实现复制,并让它返回T
。这将使is,因此您使用类型参数调用它,它将返回该类型。
public static T Copy<T>() where T : CopyableClass
{
T retVal = new T();
// do whatever copying is required
return retVal;
}
称之为你做;
DerivedClass d = Copy<DerivedClass>();
实际执行复制的代码可能需要更多的工作来实现泛型,但这是值得的,因为您将有一个适用于任何派生类型的Copy()
实现。我不知道这个方法中的逻辑是什么,所以我只是把它删掉了。此外,我建议您查看一般的泛型。对于这样的事情,它们通常是最好的选择。如果您的实现需要对基类是唯一的,请保持相同的方法定义,但使其抽象,然后在基类中重写它。