继承泛型抽象

本文关键字:抽象 泛型 继承 | 更新日期: 2023-09-27 18:16:57

我不确定这是否可能,寻找一些澄清。

我有一个这样的类结构:
public class FooBase
{
    //Some base class
}
public class BarBase
{
    //Some base class    
}
public class Foo : FooBase
{
    //Implementation
}
public class Bar : BarBase
{
    //Implementation
}
public abstract class FooBarHolderAbstract<T, V> where T: FooBase where V: BarBase
{
}
public class MyFooBarHolderImpl : FooBarHolderAbstract<Foo, Bar>
{
}
public class FooBarTest
{
    public void DoSomethingWithFooBar<T>() where T : FooBarHolderAbstract<FooBase, BarBase>
    {
        //Do something tith the obj
    }
    public void RunTest()
    {
        //This doesn't work, compiler says MyFooBarHolder is not convertible to FooBarHolderAbstract<FooBase, BarBase>
        DoSomethingWithFooBar<MyFooBarHolderImpl>();
    }
}

在FooBarTest类中,我想创建一个接受泛型参数的方法,该方法继承自具有两个泛型参数的抽象类。类MyFooBarHolderImpl扩展了抽象基类,并使用继承抽象类泛型参数类型的类型指定其泛型参数。

当我尝试调用这个方法(DoSomethingWithFooBar())编译器告诉我类型MyFooBarHolderImpl必须转换为FooBarHolderAbstract

这是不能做的事情,还是我错过了一个概念/语法?

提前感谢!

继承泛型抽象

嗯,这不能直接做到——FooBarHolderAbstract<Foo, Bar> 不是 FooBarHolderAbstract<FooBase, BarBase>。不清楚你是否可以逻辑上拥有它,因为我们不知道抽象类中有什么。

你基本上是在寻找泛型协方差,但这在类上是不支持的——所以你可能想引入一个接口:

public interface IFooBarHolder<out T, out V>
    where T: FooBase
    where V: BarBase
{
    // Define what you need in here
}
public abstract class FooBarHolderAbstract<T, V> : IFooBarHolder<T, V>
    where T : FooBase
    where V : BarBase
{
}
此时,您可以将FooBarTest更改为:
public void DoSomethingWithFooBar<T>() where T : IFooBarHolder<FooBase, BarBase>
{
    //Do something with the obj
}

…因为IFooBarHolder<Foo, Bar> IFooBarHolder<FooBase, BarBase>

然而,这只有在你可以为接口定义所有使用TV在"out"位置的操作时才有效,例如方法的返回类型。如果你曾经需要它们在"输入"位置,例如作为方法参数,你卡住了-因为一个方法期望Foo不能处理任何其他类型的FooBase

这并不清楚,你要在DoSomethingWithFooBar中做什么,因为你没有传递任何参数,但这里有另一个选项:

public class FooBarTest
{
    public void DoSomethingWithFooBar<TFooBase, TBarBase>(FooBarHolderAbstract<TFooBase, TBarBase> obj) 
        where TFooBase : FooBase
        where TBarBase : BarBase
    {
        //Do something tith the obj
    }
    public void RunTest()
    {
        DoSomethingWithFooBar<Foo, Bar>(new MyFooBarHolderImpl());
    }
}

public class FooBarTest
{
    public void DoSomethingWithFooBar<TFooBase, TBarBase, THolder>() 
        where TFooBase : FooBase
        where TBarBase : BarBase
        where THolder : FooBarHolderAbstract<TFooBase, TBarBase>
    {
        //Do something tith the obj
    }
    public void RunTest()
    {
        DoSomethingWithFooBar<Foo, Bar, MyFooBarHolderImpl>();
    }
}

你必须写你的FooBarTest如下。你必须将DoSomethingWithFooBar<T>T定义为FooBarHolderAbstract<Foo, Bar>

    public class FooBarTest
    {
        public void DoSomethingWithFooBar<T>() where T : FooBarHolderAbstract<Foo, Bar>
        {
            //Do something tith the obj
        }
        public void RunTest()
        {                         
            DoSomethingWithFooBar<MyFooBarHolderImpl>();
        }
    }