6

好的,我有许多从基类派生的不同类。这个基类是一个包含常用方法的抽象。

其中一种方法是一种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
    }
}
4

4 回答 4

5

你真的不能。基类不可能知道所有未来的实现。您将不得不求助于通用抽象类(就像您所做的那样)类型或通用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,但这将是运行时错误。如果您对所有派生实现有绝对控制权(即您的抽象类也有一个内部构造函数),这不是问题。

于 2013-07-02T17:53:38.970 回答
1

该解决方案涉及中产阶级,但我认为它更符合您的需求。至少您可以获得隔离复制代码的可能好处

    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>
    {
    }
于 2017-11-16T21:30:51.357 回答
0

您实际上想在基类中实现复制并让它返回T。这将使您使用类型参数调用它并返回该类型。

public static T Copy<T>() where T : CopyableClass
{
    T retVal = new T();
    // do whatever copying is required
    return retVal;
}

称它为你做的;

DerivedClass d = Copy<DerivedClass>();

您实际执行复制的代码可能需要更多的工作才能使通用化,但值得付出努力,因为您将有一个Copy()适用于任何派生类型的单一实现。我不知道该方法中属于什么逻辑,所以我只是将事情排除在外。另外,我建议总体上检查泛型。它们通常是此类事情的最佳选择。如果您的实现需要对基类是唯一的,请保持相同的方法定义,但使其抽象化,然后在基类中覆盖它。

于 2013-07-02T17:53:43.190 回答
0

这将允许您将此基类转换为派生类型并返回它。

public abstract class BaseClass<TDerived> : where TDerived: BaseClass<TDerived>
{
   public TDerived DoSomethingCommon(string param)
   {
      var derivedType = (TElement)this;
      //do something.
      return derivedType;
   }
}
于 2014-03-07T18:50:40.480 回答