The square-rectangle problem

Julia does not support implementation inheritance. Let's list the reasons:

  • All concrete types are final, so there is no way to create new subtypes from another concrete type. Therefore, it is not possible to inherit object fields from anywhere.
  • You cannot declare any field in an abstract type because otherwise, it would be concrete rather than abstract.

The core developers of the Julia programming language made a very early design decision to avoid implementation inheritance for a number of reasons. One of them is the so-called square-rectangle problem, also sometimes called the circle-ellipse problem.

The square-rectangle problem presents a clear challenge for implementation inheritance. As we know by common sense, every square is a rectangle with an additional constraint that the length of both sides is equal. In order to model these concepts in a class-based, object-oriented language, we may attempt to create a Rectangle class and a Square subclass:

Very quickly, we realize that we have already gotten ourselves into trouble. If a Square has to inherit all fields from its parent class, then it would have inherited both width and height. But we really want to have a single field called length instead.

The exact same issue is sometimes presented as the circle–ellipse problem. In that case, a circle is an ellipse, but there is only one radius rather than major and minor axis lengths.

How do we solve this kind of problem? Well, one way is to ignore the issue and create a Square subclass without any field defined. Then, when a Square is instantiated with a particular length, both width and height fields are populated with the same value. Is that good enough? The answer is no. Given that Square also inherits the methods of Rectangle, we probably need to provide override methods for the mutating methods, such as setWidth and setHeight, so that we can keep both fields with the same value. In the end, we have a solution that seems to work functionally but is terrible in performance and memory usage.

But how did we get into trouble in the first place? To analyze this further, we should realize that a square, while it can be classified as a rectangle, is a more restrictive version of a rectangle in nature. This is already starting to sound unintuitive—typically, when we create subclasses, we extend the parent class and add more fields and functionalities. When do we want to remove fields or functionality in subclasses? It already seems to be logically backward. Maybe we should make Rectangle a subclass of Square? That does not sound very logical either.

We end up with a conundrum. On one hand, we would like to model real-world concepts properly in code. On the other hand, the code does not really fit without causing maintenance or performance issues. By now, we cannot help but ask ourselves whether we really want to write code to work around problems with implementation inheritance. We don't.

Perhaps you are not yet 100% convinced that implementation inheritance is more evil than good. Let's look at another problem.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.218.234.83