Дополнительные публичные методы в производных классах? - PullRequest
5 голосов
/ 09 июня 2009

Если у меня есть абстрактный класс и производные классы этого класса, я прав, что в соответствии с хорошей практической практикой проектирования, производные классы не должны предоставлять дополнительных открытых методов (они должны реализовывать только абстрактные классы и, необязательно, переопределять родительский класс) методы)?

Кроме того, является ли приемлемой практика иметь разные сигнатуры методов конструктора для каждого производного класса?

Ответы [ 8 ]

5 голосов
/ 09 июня 2009

Лично я не вижу проблем ни с одним.

Что касается дополнительных открытых методов для производных классов:

Во многих случаях это ограничено. Дополнительные методы не будут использоваться, когда класс приведен или установлен на ссылку на базовый класс, что серьезно ограничивает полезность этой практики. При этом, нет ничего особенно плохого в этом подходе. Подклассы предназначены для добавления определенного поведения - иногда в иерархии классов в подклассе появляется новое поведение, которое не подходит для базового класса. Если подкласс будет часто использоваться сам по себе, то вполне разумно моделировать дополнительное поведение в методах.

Что касается сигнатур конструктора -

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

Как говорится:

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

2 голосов
/ 09 июня 2009

В целом нормально.

Чего вы хотите избежать, так это использовать специфику в общем. т.е.

foreach(Animal a in myFarm.Animals)
{
    a.Feed();
    // this is a bit grim
    if( a is Horse )
    {
       ((Horse)a).CleanStable();
    }
}

То есть дело не в добавлении публичного метода, а в том, откуда вы его вызываете.

2 голосов
/ 09 июня 2009

Это красота производных классов.

Хотя класс Pen может иметь функцию write (), класс RetractablePen, расширяющий класс Pen, также может иметь функцию retractPoint ().

Когда вы расширяете класс, это означает - буквально - расширение его функциональности.

1 голос
/ 09 июня 2009

Если вы уважаете принцип замены Лискова , вы можете делать то, что хотите.

Конечно, добавление метода к производному классу вообще не нарушает принцип.

1 голос
/ 09 июня 2009

Нет, совершенно разумно (а иногда очень необходимо по замыслу) добавлять дополнительные общедоступные методы. Рассмотрим ситуацию (полностью надуманную) абстрактного базового класса Shape, который имеет Location член и Size метод. Например, когда вы извлекаете Polygon из Shape, вы можете добавить открытый метод, например, GetNumberOfSides(); но вы не хотите иметь это, когда вы выводите Circle из Shape.

Таким же образом, производные типы могут иметь очень разные требования к конструкции; На самом деле невозможно определить, какие могут быть все требования при определении абстрактного базового класса, поэтому не стесняйтесь иметь разные подписи. Тот факт, что ваши производные типы будут полиморфны с абстрактным базовым классом, не означает, что этот базовый класс налагает строгие ограничения на то, как вы можете реализовать абстракции, определенные в этом базовом классе; вы можете делать это, как хотите.

1 голос
/ 09 июня 2009

Вполне допустимо добавлять дополнительные открытые методы к вашим производным классам. Также вполне допустимо давать им разные конструкторы. (На самом деле, это довольно распространенное явление.)

0 голосов
/ 09 июня 2009

Это не только приемлемо, но часто необходимо, чтобы конструкторы были разными. Например, если мы имеем (неизменный) Rectangle класс и расширяем его с помощью (неизменного) Square, конструктор Square должен быть (для использования Java на данный момент)

public Square(double size)

в то время как конструктор Rectangle будет

public Rectangle(double width, double height)

Что должно произойти, так это то, что конструктор подкласса должен вызвать некоторый соответствующий конструктор суперкласса.

Что касается дополнительных общедоступных методов, это может зависеть от использования. Для случая Square я бы не стал добавлять никаких дополнительных методов. Однако в Java существует подкласс PrintWriter из Writer чья цель - добавить несколько удобных методов. В этом случае я думаю, что все в порядке (у Java, конечно, есть несколько плохих примеров, но я не думаю, что это один из них). Я также ожидал бы возможности некоторых дополнительных методов для типов контейнеров / подразделов.

Чего не следует делать, так это изменять методы суперклассов таким образом, чтобы это не соответствовало ожиданиям суперкласса.

0 голосов
/ 09 июня 2009

производные классы не должны предоставлять дополнительные общедоступные методы

Может ли собака делать то, что животное не может?

Кроме того, является ли приемлемой практика иметь разные сигнатуры методов конструктора для каждого производного класса?

Здесь нет проблем. Производные типы не обязательно должны соответствовать сигнатурам конструкторов их братьев и сестер или родителей.

...