Который должен наследовать какой? - PullRequest
3 голосов
/ 18 июля 2009

Это один из скучных академических вопросов ООП, но это не домашнее задание . Я получил вопрос от начинающего программиста об одном из этих глупых примеров из учебников об ООП.

Представьте, что вы разрабатываете класс Square и класс Cube, который должен наследовать какой?

Я вижу отношения, но что это такое, я не вижу на самом деле!

Не могли бы вы дать мне логический аргумент с учетом ООП.

Ответы [ 8 ]

22 голосов
/ 18 июля 2009

Ни! Поскольку квадрат не является кубом, а куб не является квадратом, он также не должен наследовать от другого. Квадрат может наследовать от многоугольника, а куб - от многогранника, но оба они взаимоисключающие.

14 голосов
/ 18 июля 2009

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

Как бы вы построили, это зависит от того, как вы моделируете. Вы можете пойти с чем-то вроде куба, имеющего 6 квадратов (куба нет, у него 6 квадратов; композиция), или куб имеет размер стороны, как у квадрата. Но как только не будет "есть", наследование станет опасной зоной ...

Кроме того, в наследстве все, что является допустимым для базового класса, должно быть допустимым для производного . Это квадрат расширяет проблему прямоугольника . Например:

Предположим, что Cube наследует Square: Если у вашего Square есть метод changeArea (double area) и getSide (), то же самое должно быть возможно для Cube. Но это не так, поскольку площадь куба в 6 раз больше площади квадрата (у него 6 квадратов).

Предположим, что Square наследует куб: Если у вашего куба есть метод setVolume (двойной объем), ваш квадрат будет разбит, если у него нет объема

Наконец, если вы хотите использовать наследование, вы можете создать объект GeometryObjectWithEqualSides , тогда оба объекта могут наследовать его. :)

6 голосов
/ 18 июля 2009

Если так или иначе, это будет нарушением принципа замены Лискова .

1 голос
/ 22 июля 2009

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

Гиперкуб мог бы предоставить функции / методы, которые возвращают значения для числа вершин, ребер, граней и т. Д. Для этого конкретного экземпляра.

См. Гиперкуб в Википедии для получения дополнительной информации.

1 голос
/ 18 июля 2009
struct Square // Rectangle actually
{
  Square( int dx, int dy ) : dx(dx), dy(dy) {};

  int dx;
  int dy;

  int floor_area() { return dx*dy; };
};

struct Cube : Square  // Cuboid actually
{
  Cube( int dx, int dy, int dz ) : Square(dx, dy), dz(dz) {};

  int dz;

  int cube_area() { return floor_area()*2+dx*dz*2+dy*dz*2; };
};

Кажется, что принцип подстановки Лискова здесь не нарушается.

1 голос
/ 18 июля 2009

Оба наследуются от гиперкуба

0 голосов
/ 18 июля 2009

Большинство комментариев здесь правильно говорят о том, что ни один из них не должен наследоваться от другого. Это верно в большинстве случаев. Но я думаю, что есть более общий ответ: Это зависит от ваших ожиданий от них. Вы ожидаете, что площадь будет делать что? Куб также делает это? Может быть, другой путь - можете ли вы использовать Квадрат каждый раз, когда используете Куб? Я думаю, что оба утверждения «Куб делает все, что делает Квадрат» и «Квадрат делает все, что делает Куб», в соответствии со здравым смыслом, являются ложными, поэтому ни одно из них не должно наследоваться от другого. Однако вам решать, какова их структура и поведение, потому что именно вы сами определяете, что делает ваша программа и из чего она состоит.

Скорее всего, "Куб содержит 6 квадратов" - это отношения, которые вы видели.

0 голосов
/ 18 июля 2009

Ни один не должен наследовать другого. Один - это двумерная форма, другой - трехмерный объект. Между этими двумя понятиями действительно недостаточно сходства, чтобы оправдать наследование.

Теперь вы можете создать куб , состоящий из квадратов, если вам нужен отдельный объект для каждой стороны;)

...