2009-06-09 6 views
5

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

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

+0

* EDIT * FYI, я имею в виду случай, когда вы строите объект с завода. Я утверждаю, что код вызова, в случае фабрики, должен знать, какие методы ожидать от производных классов. –

ответ

5

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

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

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

Что касается подписей конструктора -

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

Это, как говорится:

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

+0

Если вы строите объект с завода, скажем, тогда я прав, что не должно быть дополнительных общественных методов? Должен ли код вызова, в случае фабрики, знать, какие методы следует ожидать? –

+0

Это зависит - даже если вы строите завод, фабрика должна знать тип времени компиляции объекта (для вызова соответствующего конструктора). Он может «знать» о дополнительных параметрах. В этом случае, однако, это действительно зависит от сценария, от того, как он будет использоваться и т. Д. –

1

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

0

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

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

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

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

+0

Чтобы ответить на вопрос yr, Да Собака может делать то, что некоторые животные не могут сделать ... Как кора, укус, бег, сарай, прыжок и т. Д. Черви - это животные (они не растения) - и червь не может выполнять какие-либо из этих действий ... –

2

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

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

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

+0

Если вы строите объект с завода, скажем, тогда я прав, что не должно быть дополнительных общественных методов ? Должен ли код вызова, в случае фабрики, знать, какие методы следует ожидать? –

+0

Если вы строите его с завода, то, вероятно, вы используете полиморфизм и смотрите на класс, как если бы он был его родителем. В этом случае у вас не будет доступа к методам, определенным в дочернем классе, если вы не проверили instanceof и не произвели его. –

1

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

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

2

Это нормально в целом.

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

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

Таким образом, это не акт добавления общедоступного метода, а скорее того, где вы их вызываете.

+0

Я хочу лошадь, которая очищает свою собственную конюшню! Где я могу его получить? ;) –

+0

Да ... Я знаю ... я пишу во время сборки, поэтому у меня нет времени быть таким педантичным, как я обычно ...: (... это будет сделано. – Quibblesome

0

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

public Square(double size) 

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

public Rectangle(double width, double height) 

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

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

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

1

Если вы уважаете Liskov substitution principle, вы можете делать то, что хотите.

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

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