2013-10-07 177 views
1

我正在C#中使用ASP.NET MVC。我正在创建服务类。我有一个驱动程序服务接口(IDriverService)的服务接口。实现接口但返回返回类型的子类?

它具有以下方法定义:

Driver New(); 

我有这个接口,将实现该方法,这样的两种实现方式:

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

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

正如你可以看到一个实现通过实现新方法返回一个基础Driver,另一个是Driver的一个子类。

问题是通过实现接口我必须返回一个'驱动程序',但有时我想返回'SubclassOfDriver'。我可以说你应该把结果投给你想要的驱动程序,但这是不安全的,编码器需要关于实现的信息来确定哪个驱动程序已经被实例化。这样做的最好方法是什么?

感谢

+0

您可以返回界面而不是类(因此'IDriver New();') – Raidri

+1

投射到基类并非不安全,甚至不是必需的。这是一个隐含的安全转换。 –

+0

客户端不应该关心哪个'Driver'被实例化 - 如果他这样做,这是一种设计气味。 – millimoose

回答

1

SubclassOfDriver一个Driver

没有什么不对。

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

您可以使用泛型:

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 ...; 
    } 
} 
2

的问题是通过实现接口I必须返回Driver但有时我想返回SubclassOfDriver

问题不在于返回Driver,而是“有时希望返回类型为SubclassOfDriver”。如果您的代码在某些情况下需要实现您的IDriverService以返回派生类型,那么您已选择了错误的抽象级别来满足您的需求。将接口隐藏起来的原理(即将SubclassOfDriver隐藏在Driver的后面)是你永远不需要拨打特定于SubclassOfDriver的呼叫。

解决此问题的一种方法是重构Driver类以包括其他方式不可用的方法SubclassOfDriver。你可以让这些方法是可选的,让调用者测试一个特定的子类是否实现它们。