简体   繁体   English

如何使用实现类的类型的参数创建抽象方法

[英]How to create an abstract method with a parameter of type of implementing class

I have got a abstract class with an abstract method taking a parameter of the type of the implementing class. 我有一个抽象类,抽象方法采用实现类的类型的参数。 I can achieve this by generics like this: 我可以通过这样的泛型实现这一点:

abstract class Clazz<T>
{
   public abstract void CopyFrom(Clazz<T> source);
}

class MyClass : Clazz<MyClass>
{
  public override void CopyFrom(Clazz<MyClass>)
  {
    // implementation
  }
}

Unfortunately I need in one of the implementing classes a list of Clazz<T> elements. 不幸的是,我需要在其中一个实现类中包含一个Clazz<T>元素列表。 So how can I achieve this? 那我该怎么做呢?

  • Of cause List<Clazz<T>> does not work. 因为List<Clazz<T>>不起作用。
  • List<Clazz<MyClass>> is too restrictive. List<Clazz<MyClass>>限制性太强。
  • Removing the generics and the abstract method does work (my current solution), but this way I could forget to implement the CopyFrom() method in one of the implementing classes. 删除泛型和抽象方法确实有效(我当前的解决方案),但这样我就忘记在其中一个实现类中实现CopyFrom()方法。

Edit: Here comes a more detailed example: I've got an abstract class: 编辑:这里有一个更详细的例子:我有一个抽象类:

abstract class Clazz<T>
{
    public abstract void CopyFrom(Clazz<T> source);
    // ...
}

And a derived class: 派生类:

class MyDerivedClass : Clazz<MyDerivedClass >
{
    public string Text;
    private readonly List<MySubClass> _list = new List<MySubClass>();

    public override void CopyFrom(MyDerivedClass source)
    {
        Text = source.Text;
    }

    private List<Clazz> GetAllItems()
    {
        List<Clazz> list = new List<Clazz>();
        list.Add(this);
        list.AddRange(_list);
    }


    private class MySubClass : Clazz<MySubClass>
    {
        public int Number;

        public override void CopyFrom(MySubClass source)
        {
            Number = source.Number;
        }
    }
}

There are several other deriving classes, the GetAllItems() Method is only needed in MyDerivedClass . 还有其他几个派生类, GetAllItems()方法仅在MyDerivedClass需要。

You can make the respective method generic, too, and introduce a constraint that takes T into account. 您也可以使相应的方法通用,并引入一个将T考虑在内的约束。 If I understand well what you want to achieve, you can do this: 如果我很清楚你想要实现的目标,你可以这样做:

abstract class Clazz<T>
{
   public abstract void CopyFrom(Clazz<T> source);

   public abstract void ProcessList<TDescendant>(List<TDescendant> list)
       where TDescendant : Clazz<T>;
}

class MyClass : Clazz<MyClass>
{
    public override void CopyFrom(Clazz<MyClass> source)
    {
        // implementation
    }

    public override void ProcessList<TDescendant>(List<TDescendant> list)
    {
        // implementation
    }
}

You can also easily include list processing in a descendant, like this: 您还可以轻松地在后代中包含列表处理,如下所示:

class MyOtherClass : Clazz<MyOtherClass>
{
    public override void CopyFrom(Clazz<MyOtherClass> source)
    {
        // implementation
    }

    // this list processing is inherited
    public override void ProcessList<TDescendant>(List<TDescendant> list)
    {
        // implementation
    }

    // this list processing is specific to this descendant only
    public void ProcessMyClassList<TDescendant>(List<TDescendant> list)
        where TDescendant : Clazz<TMyClass>
    {
        // implementation
    }
}

Then use can declare a descendant of MyClass , which in turn is a Clazz<T> , T being MyClass : 然后使用可以声明MyClass的后代,而后者又是一个Clazz<T>TMyClass

class MyDescendant : MyClass
{ 
}

The following works: 以下作品:

List<MyDescendant> list = new List<MyDescendant>();
new MyClass().ProcessList(list);

In case of MyOtherClass , the situation is a little bit different. MyOtherClass的情况下,情况有点不同。 ProcessMyClassList accepts a list of Clazz<T> or its descendants; ProcessMyClassList接受Clazz<T>或其后代的列表; however, not those related to MyOtherClass but to the good-ol' MyClass . 然而,不是那些与MyOtherClass相关的,而是与好的' MyClass相关的那些。 This code works: 此代码有效:

List<MyDescendant> list = new List<MyDescendant>();
new MyOtherClass().ProcessMyClassList(list); // this works

But the following won't compile: 但以下内容无法编译:

List<MyOtherClass> list = new List<MyOtherClass>();
new MyOtherClass().ProcessList(list);        // this works
new MyOtherClass().ProcessMyClassList(list); // this doesn't

would this suffice? 这样就够了吗? without more details it is hard to tell. 没有更多细节,很难说清楚。

interface ICopyMaker
{
    void CopyFrom(ICopyMaker source);
}

abstract class Clazz<T> : ICopyMaker
{
   public abstract void CopyFrom(Clazz<T> source);

   void ICopyMaker.CopyFrom(ICopyMaker source)
   {
       var src = source as Clazz<T>;
       if (src == null) return; // know how to copy only from the instances of the same type

       CopyFrom(src);
   }
}

class MyClass : Clazz<MyClass>
{
    private List<ICopyMaker> _list = new List<ICopyMaker>();

    public override void CopyFrom(Clazz<MyClass> c)
    {
    //implementation
    }
}

Thank's everyone for your answers, but I think I have figured out a solution I can live with: I will remove the generics and add a typecheck, like in the solution from anikiforov: 感谢大家的答案,但我想我已经找到了一个可以忍受的解决方案:我将删除泛型并添加一个类型检查,就像anikiforov的解决方案一样:

Abstract class: 抽象类:

abstract class Clazz
{
   public abstract void CopyFrom(Clazz source);
}

And the derived class: 派生类:

class MyDerivedClass : Clazz
{
    public string Text;
    private List<MyNestedClass> _list;

    public override void CopyFrom(Clazz source)
    {
        var src = source as MyDerivedClass;
        if (src == null) return;
        Text = src.Text;
    }

    public List<Clazz> GetAllItems()
    {
        var list = new List<Clazz>();
        list.Add(this);
        list.AddRange(_list);
        return list;
    }

    class MyNestedClass : Clazz
    {
        public int Number;
        public override void CopyFrom(Clazz source)
        {
            var src = source as MyNestedClass;
            if (src == null) return;
            Number = src.Number;
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 实现抽象方法时更改参数类型 - Change parameter type when implementing an abstract method 使用继承的类作为参数类型覆盖抽象方法 - Overriding abstract method with the inherited class as parameter type 在使用抽象基 class 作为参数实现接口方法时访问派生的 class 属性 - Accessing derived class properties when implementing an interface method with abstract base class as parameter 如何创建抽象构造函数或获取抽象类的类型并返回它? - How to create an abstract constructor or get type of abstract class and return it? 以抽象类作为参数的方法 - Method having an abstract class as a parameter 如何将抽象类作为参数传递给类型的实例? - How do I pass abstract class as parameter for instance of type? 如何通过子类作为参数来覆盖抽象方法? - How to pass sub-class as a parameter to override an abstract method? 如何在具有不同类作为输入参数的抽象类中定义方法? - How to define a method in abstract class with different classes as input parameter? 具有抽象请求类型的WCF Rest方法-错误:无法创建抽象类 - WCF Rest Method with abstract request type - Error: Cannot create an abstract class CS0051:参数类型“抽象类”比方法“方法”更难访问 - CS0051: Parameter type 'abstract class' is less accessible than method 'method'
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM