2013-10-07 2 views
1

Я работаю с ASP.NET MVC в C#. Я создаю классы обслуживания. У меня есть служебный интерфейс для сервисных интерфейсов драйвера (IDriverService).Реализация интерфейса, но возвращающий подкласс возвращаемого типа?

Это следующее определение метода:

Driver New(); 

У меня есть две реализации этого интерфейса, который реализует этот метод как таковой:

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

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

Как вы можете видеть одну реализацию реализует Новый метод, возвращая базовый драйвер, а другой - для некоторого подкласса драйвера.

Проблема заключается в реализации интерфейса, который я должен вернуть «Драйвер», но иногда я хочу вернуть «SubclassOfDriver». Я мог бы сказать, что вы должны отдать результат драйверу, который вы хотите, но это небезопасно, и кодер потребует информации о реализации, чтобы определить, какой драйвер был создан. Каков наилучший способ сделать это?

Благодаря

+0

Вы можете вернуть интерфейс вместо класса (так что IDriver New(); ') – Raidri

+1

Кастинг в базовый класс небезопасен и даже не нужен. Это неявное безопасное преобразование. –

+0

Клиент не должен заботиться о том, какой экземпляр «Драйвер» был создан - это дизайнерский запах, если он это делает. – 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, которые недоступны в противном случае. Вы можете сделать эти методы дополнительными, позволяя вызывающим абонентам проверять, реализует ли их какой-либо конкретный подкласс или нет.

Смежные вопросы