2014-01-23 2 views
-1

Я новичок в дизайне и программировании OO, и у меня есть вопрос, который, я считаю, касается дизайна класса. Я буду настолько точным, насколько я могу в своей терминологии.Дизайн и наследование классов

[Изменить] Возможно, это сводится к следующему: у меня есть список объектов типа базового класса. Производные классы создаются как конкретные типы базового класса, реализующие методы базового класса, а некоторые с дополнительными параметрами и/или методами, специфичными для производного типа. Когда я пересекаю список, я работаю с базовым классом. Каким образом можно получить доступ к методам и параметрам для определенного варианта класса? Выключить инструкции и кастинг? Разве это не плохая форма на C# и не указывает на дефект в дизайне класса?

[Оригинал] Следуя примеру Строуступа в книге «Язык программирования на С ++», предположим, что я пишу графическую программу, использующую «форму» базового класса, и классы «круг», «треугольник», и «квадрат», которые получены из «формы». Согласно Stroustrup, базовый класс должен содержать функции-члены, необходимые для реализации «полного набора операций» для класса формы. В большинстве случаев эти функции-члены будут виртуальными, так что производные классы могут реализовать функциональные возможности, специфичные для их формы, такие как: загрузка, сохранение, рисование, поворот, обновление и т. Д. Это все имеет смысл для меня.

Где я сталкиваюсь с трудностями - это влияние тонких различий между типами фигур и последствиями этих различий в базовом классе. Например, рассмотрим функции-члены, специфичные для определенной производной формы. Предположим, что форма «круг» имеет значение, описывающее, сколько сегментов линии используется для приближения круга (например, lineCount). Как обрабатывать параметр и обновлять это значение таким образом, чтобы не начинать загрязнять мой базовый класс виртуальными функциями-членами, «пузыряться» от конкретных потребностей каждого из производных классов?

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

Чтобы решить эту проблему, я нахожусь на правильном пути, чтобы думать, что помимо очевидных функций-членов, таких как «рисовать», я должен глубоко подумать о требовании «полного набора операций». Поэтому, если у меня есть конкретное значение формы (например, lineCount для формы круга), оно должно быть возможным через функции-члены формы, чтобы получить/установить это значение в общем виде, совместимом с другими (возможно, разными) значениями из другого формы. Я могу только думать, что класс формы должен поэтому включать в себя общую функцию настройки параметров, которая может включать в себя требование, чтобы каждый производный класс представлял свою собственную форму пользовательского интерфейса, запрашивая ее конкретные параметры конкретной формы. Требование класса формы к включению функций-членов пользовательского интерфейса кажется, что класс формы становится слишком тяжелым.

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

+0

Один из способов решения этой проблемы - иметь конфигурационные данные 'std :: map' (или' Dictionary' для C#) и виртуальную функцию 'configure', которую вы можете вызывать для передачи необходимых данных для каждого типа фигуры. –

+0

Все подклассы должны реализовывать «полный набор операций» в базовом классе. Но это не означает, что базовый класс должен поддерживать все операции, которые может иметь любой подкласс. Просто поместите такие функции только в подкласс, который ему нужен. – user2079303

+0

Zac, это ваш комментарий, связанный с решением конкретной проблемы ВСЕХ кругов, нуждающихся в значении lineCount, где значение одной строки, сохраненное в качестве параметра конфигурации, может применяться ко всем кругам. Если так, я верю, что понимаю, что вы говорите. Но моя проблема более общая, каждый конкретный тип формы имеет уникальные значения, которые уникальны для него в одиночку. Есть ли решение лучше, чем «Полный набор операций» или с помощью операторов casts/switch на объектах формы типа, хранящихся в списке? – BobC

ответ

0

user2079303 точка хорошая, и я думаю, вы можете быть смущены языком «полный набор операций» - это просто означает, что класс Shape должен знать, как делать все, что вы хотите делать с Shape s, а не то, что он должен знать, как делать все, что вы хотите делать с кругами и треугольниками и так далее. Это нормально, если у вас есть метод changeLineCount() только в классе Circle, если вы в порядке, только имея возможность изменить количество строк Circle объектов (вещи, которые, как вы знаете, определенно окружены), а не Shape объекты (вещи, которые могут быть или не быть кругами).

Я не могу представить ситуацию, когда вы хотите изменить количество строк, которые вы не знали, потому что это были круги. Это не преступление, чтобы использовать оператор switch, чтобы выяснить, есть ли что-то в круге, если изменение количества строк не имеет смысла для прямоугольников (и я не знаю, как это будет).

+0

Согласен, что строкаCount не имеет смысла для прямоугольника. То, что вызывает у меня наибольшую путаницу, заключается в том, что после того, как объекты класса круга помещаются в список фигур, я не знаю, как их вернуть обратно в круги, поэтому я могу получить доступ к функции-члену. Правильно ли выбрасывает? Из того, что я читал, на строго типизированном языке, таком как C#, если я кастую, то я делаю что-то не так в моем дизайне. – BobC

+0

@BobC не относится ко всем этим правилам хорошего стиля как к абсолютным, почему вы думаете, что есть листинг, если неправильно использовать его? Переключение по типу «плохо», потому что когда добавляется новый тип, вам придется идти повсюду и исправить все эти ключи. Теперь, если у вас ограниченный и редко расширенный набор типов (например, фигуры в графическом редакторе)? Другой вопрос: почему ваши фигуры (предположительно созданные пользователем через интерфейс) знают, как сделать себя? Это то, что заставляет вас разоблачить особенности алгоритма обработки в интерфейсе формы. –

0

Вам нужно подумать, что означает lineCount Среднее значение для прямоугольника. Если вы выясните, что концепция хорошо применима ко всем формам, то это хороший кандидат, чтобы положить в класс shape. Если, с другой стороны, это не имеет смысла для прямоугольника, то он, вероятно, принадлежит только классу окружности.

Теперь, если у вас есть массив shape, вы должны игнорировать фактическую реализацию.Если только круг имеет lineCount, это нормально, однако, когда вы работаете с массивом фигур, вы не собираетесь использовать что-либо, что связано с lineCount, потому что оно не распространяется на все фигуры (что будет означать для установки lineCount для прямоугольник?)

+0

Итак, я ставлю lineCount как функцию-член только для класса окружности. Теперь, когда я ссылаюсь на объект круга через список фигур, я больше не могу видеть функцию члена LineCount. Когда я хочу использовать эту функцию-член в форме круга, мне нужно передать ссылку на форму в класс круга. Это хорошая форма? – BobC

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