通过子类型参数从类接口继承方法:是否可能?

本文关键字:方法 是否 继承 接口 类型参数 | 更新日期: 2023-09-27 17:50:36

假设我从IMyManager继承了一个SetModel。如果我实现它,我通常会这样写:

using lib.model;
namespace MyComponents
{
    public class MyManager:IMyManager
    {
        public void SetModel(ILibModel model)
        {
        }
    }
}

这对编译器来说很好。

现在让我们说,而不是ILibModel我传递一个具体类MyModel实现ILibModel。

当MyModel是ILibModel类型时,为什么编译器不接受这个:

namespace MyComponents
{
    public class MyManager:IMyManager
    {
        public void SetModel(MyModel model) {
        }
    }
}

通过子类型参数从类接口继承方法:是否可能?

假设MyModel实现ILibModel,这不起作用的原因是,虽然所有MyModel类型都是ILibModel类型,但反之并不成立。也就是说,并非所有ILibModel类型都是MyModel类型。

接口明确地声明它必须使用ILibModel类型。因此,仅采用MyModel的实现不符合您的接口契约,因为一个类型,例如也实现ILibModelMyOtherModel,是基于您的接口契约传入的有效类型。

解决这个问题的唯一方法可能是在接口上使用泛型。例如:
public interface IMyManager<TModel>
    where T : ILibModel
{
    void SetModel(TModel model);
}
public class MyManager : IMyManager<MyModel>
{
    void SetModel(MyModel model)
    {
    }
}

然而,对于这样的系统,您可能会遇到协方差和反方差的问题。

因为你为SetModel函数提供了一个重载。就编译器而言,也许您希望允许程序员对具体类型执行更具体的操作,而对接口版本执行其他操作。

因为以后有人会写:

((IMyManager)myManager).SetModel(new OtherClassThatImplementsILibModel());

因为IMyManager是这样定义SetModel的。