实现接口但返回返回类型的子类?

时间:2013-10-07 14:00:39

标签: c# inheritance interface casting

我正在使用C#中的ASP.NET MVC。我正在创建服务类。我有一个驱动程序服务接口的服务接口(IDriverService)。

它有以下方法定义:

Driver New();

我有两个实现此接口的接口实现:

Driver New()
{
   return new Driver();
}

Driver New()
{
   return new SubclassOfDriver();
}

正如您所看到的,一个实现通过返回基本驱动程序来实现New方法,另一个实现用于Driver的某个子类。

问题是通过实现接口我必须返回'Driver',但有时我想返回'SubclassOfDriver'。我可以说你应该把结果转换成你想要的驱动程序,但这是不安全的,并且编码器需要有关实现的信息以确定哪个驱动程序已被实例化。这样做的最佳方式是什么?

由于

4 个答案:

答案 0 :(得分:6)

您可以使用显式接口实现有效地重载返回类型:

Driver IDriverService.New()
{
   return New(); // Calls the method below
}

public SubclassOfDriver New()
{
   return new SubclassOfDriver();
}

现在任何只知道你的实现作为接口实现的代码都会看到显式接口实现方法,并期望返回类型为Driver

通过其具体类型引用服务的任何代码只能看到第二个方法,并期望返回类型为SubclassOfDriver。例如:

SpecialFactory specialFactory = new SpecialFactory();
SubclassOfDriver subclassDriver = specialFactory.New(); // Fine
IDriverFactory generalFactory = specialFactory;
IDriver generalDriver = generalFactory.New(); // Fine
// This wouldn't compile
SubclassOfDriver invalid = generalFactory.New();

或者,您可能希望使您的界面具有通用性:

public interface IDriverFactory<TDriver> where TDriver : Driver
{
    TDriver New();
}

public class SpecialDriverFactory : IDriverFactory<SubclassOfDriver>
{
    public SubclassOfDriver New()
    {
        return new SubclassOfDriver();
    }
}

答案 1 :(得分:2)

  

问题是通过实现我必须返回Driver的界面,但有时我想要返回SubclassOfDriver

问题不在于返回Driver,而在于“有时希望返回类型为SubclassOfDriver”。如果您的代码需要实现IDriverService以在某些情况下返回派生类型,那么您已经选择了符合您需求的抽象级别。将实现隐藏在接口后面的原则(即隐藏SubclassOfDriver后面的Driver)是你永远不需要进行特定于SubclassOfDriver的调用。

解决此问题的一种方法是重构Driver类以包含SubclassOfDriver的方法,否则这些方法不可用。您可以将这些方法设置为可选,让调用者测试特定子类是否实现它们。

答案 2 :(得分:1)

SubclassOfDriver 一个Driver

这没有错。

答案 3 :(得分:1)

您可以使用泛型:

public class Driver { }
public class SubclassOfDriver : Driver { }

public interface IDriverService<T> where T : Driver
{
    T New();
}

public class SpecificService : IDriverService<Driver>
{
    public Driver New()
    {
        return ...;
    }
}

public class OtherSpecificService : IDriverService<SubclassOfDriver>
{
    public SubclassOfDriver New()
    {
        return ...;
    }
}