Which should inherit which?

Asked
Viewd440

4

This is one of the boring academic OOP questions, but it is not a homework. I got the question from a newbie programmer about one of those stupid textbooks examples about OOP.

Imagine that you are designing a Square class and a Cube class, which should inherit which?

I see a relationship, but what it is, I can not really see!

Could you give me a logical argument with OOP in mind.

  • Square inherits Polygon, and Cube inherits Movie.

    aehiilrs17 июля 2009, 21:09

8 ответов

22

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

  • You could also mention composition. A Cube can be composed of six Squares constrained in a specific relationship.

    Mark Canlas17 июля 2009, 21:31
  • It does make sense to me :) Thanks.

    AraK17 июля 2009, 21:28
  • I agree: neither. I could see a has-a relationship, however: a Cube has a collection of 6 Squares.

    Nelson17 июля 2009, 21:15
7

Having it either way would be a violation of the Liskov Substitution Principle.

0

Neither should inherit the other. One is a 2-dimensional shape, the other is a 3-dimensional object. There really isn't enough similarity between the two to justify inheritance.

Now you might conceivably make a cube composed of squares, if you need a separate object for each side ;)

1

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

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

Дополнительную информацию см. в Hypercube в Википедии.

0

Most of comments here are correctly saying that none of them should inherit from another. This is true in most cases. But I think there is more generic answer: It depends on your expectations on them. You expect Square to do what? Does Cube also do it? May be the other way - can you use Square whenever you use Cube? I think both statements "Cube does all what Square does" and "Square does all what Cube does" are false, according to common sense, so none of them should inherit from another. However, it is up to you to decide their structure and behavior, because it is you who defines what your program does and what it consists of.

Most likely "Cube contains 6 Squares" is the relationship that you saw.

1

Both inherit from hypercube

  • Actually, they are. A hyper cube is another name for what might be called an N-cube. a square is a 2-cube, a cube is a 3-cube, etc.

    Mike Cooper17 июля 2009, 21:12
  • No. A square isn’t a cube, a cube isn’t a hypercube, a square isn’t a hypercube.

    Svante17 июля 2009, 21:06
1
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; };
};

Seems to be that Liskov substitution principle is not violated here.

  • Если говорить ближе к коду, куб имеет квадрат (основание) и высоту, но это не квадрат. Вы не можете использовать Куб там, где требуются квадраты (если пирамида имеет квадратное основание, вы не можете использовать там Куб).

    David Rodríguez - dribeas17 июля 2009, 21:28
  • I’ll be able to use Cube in pyramid with z=0.

    Kirill V. Lyadvinsky17 июля 2009, 22:02
  • This is erroneous. What is the implementation of the area() method? Would it be the area of all sides or that of the base? I have a room that I want to floor. I go to the shop and ask for squares that I can use (different materials) but the tender gives me concrete cubes…

    David Rodríguez - dribeas17 июля 2009, 21:26
  • Hmmm…! Although I disagree with the logic your answer implies, every example that comes to mind actually supports your answer. Grrr!

    Bob Kaufman17 июля 2009, 21:15
15

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

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

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

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

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

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

  • A cube has 6 square shaped faces but is not a square, there really is no is-a relationship between the two

    HasaniH17 июля 2009, 20:30
  • Но в этом случае я бы с вами согласился ... мало что вы бы унаследовали от квадрата, который не нужно было бы перегружать

    TheTXI17 июля 2009, 20:28
  • A cube IS A square but with a third dimension (depth)

    TheTXI17 июля 2009, 20:27
  • Хм. Это поднимает еще один вопрос. Реализовать IEquateral и наследовать от Polygon или ThreeDimensional или реализовать IPolygon или IThreeDimensional и наследовать от Equateral?

    Я склонялся к первому, но теперь второе имеет больше смысла; по крайней мере, Equateral может установить свойство SideSize, в то время как все, что вы делаете с Polygon и ThreeDimensional, - это переопределение Area () и Volume ()…

    aehiilrs17 июля 2009, 21:33