Соединение подклассов и пример в .NET - PullRequest
0 голосов
/ 01 марта 2012

Я только что прочитал статью , в которой говорится:

Муфта подкласса. Когда базовый тип (обычно класс) имеет несколько производных типов, расширяющих его, другие типы в идеале должны знать только о базовом типе. Если все подтипы имеют один и тот же открытый интерфейс (открытые члены, унаследованные от базового типа, перезаписанные для различного поведения в каждом подклассе), то внешние «клиентские» типы могут обрабатывать их одинаково, как если бы они были базовым классом. Если это не так, если тип клиента знает особенности существующих подтипов, то это связь подкласса с рассматриваемой полиморфной структурой.

В частности, последняя строка говорит, что «если тип клиента знает особенности о существующих подтипах…». В .NET, если я использую WebRequest.Create("ftp://...");, я знаю, что будет возвращен FtpWebRequest, и я могу изменить свойства, относящиеся к подклассу FtpWebRequest, например, свойство UseBinary. Я бы не смог этого сделать, если бы у меня не было конкретных знаний о подтипе WebRequest, поэтому, на мой взгляд, это случай соединения подклассов и плохой дизайн.

Я изо всех сил пытаюсь поверить, что это плохой дизайн со стороны разработчиков .NET Framework, и вместо этого представляю, что мое понимание вышесказанного немного не в порядке. Кто-нибудь сможет объяснить, почему пример, который я привел в .NET, не является примером соединения подкласса?

1 Ответ

1 голос
/ 01 марта 2012

Я бы сказал, что это зависит.Большую часть времени вы не хотите работать с конкретными типами, такими как ваш FtpWebRequest, так как это делает вас связанными с этим типом.Если вы вместо этого работаете с интерфейсом, называемым IRequest или IWebRequest, вы не будете так привязаны к конкретной реализации этого интерфейса, что означает, что большую часть времени вам будет проще тестировать ваш код, и у вас будет меньшеболь при переходе с ftp на какой-то другой протокол, если он соответствует используемому вами интерфейсу.Но если вы делаете что-то действительно простое, вам может не понадобиться добавлять дополнительные уровни абстракции, которые создают интерфейсы.

Простой пример:

public interface IDoSomething { void DoSomething(); }
public class DoSomethingA { public void DoSomething(); }
public interface DoSomethingB { public void DoSomething(); }

public class UseDoSomething
{
    public UseDoSomething(IDoSomething do) { do.DoSomething(); }
}

Если вы в классе UseDoSomething взял в одном из конкретных типов;DoSomethingA или DoSomethingB, у вас будет более тесная связь с этой реализацией.В приведенном мною примере вы можете использовать любую реализацию IDoSomething в качестве входных данных для UseDoSomething, что отлично подходит для будущего, а также облегчает тестирование.Как вы понимаете, все зависит от ваших требований и т. Д. Может быть, вы должны использовать конкретный тип, так как вам нужен доступ к этой конкретной вещи типа, тогда это может быть хорошо.

Я проясню?

...