3

Is there a way to use the existing features of object oriented programming languages to work around the square/rectangle problem?

Can a child be defined in terms of being a more restrictive subset of its parent class rather than being defined in terms of additional features?

Former question:

I'm trying to reconcile the difference between object-oriented inheritance and a real-world taxonomy where each child type has FEWER traits than its parent. Inheritance is subtractive. In OO, inheritance is additive.

Suppose we have a class Person. A Person can either be a Customer, with billing info, or an Employee, assigned a department. Further an Employee can either be a Supervisor with direct reports, or a Worker with assignments.

Classical OO inheritance would have Worker/Supervisor inherit from Employee which inherits from Person, where each child class has more characteristics than its parent class.

In the real world, though, it's the reverse: A Mammal has lots of potential features, a Canine has a subset of those features, and a Beagle has an even smaller subset.

Another way to look at it, A quadrilateral can be any shape with four sides. A parallelogram is a quadrilateral with parallel sides. A rectangle is a parallelogram with 90 degree angles, and a square is a rectangle with equal sides.

If I were to model a real-world taxonomy using OO inheritance, how would it be done?

I could start with a parent Square, with a length, and its child be a Rectangle with a length and a height, etc., but this is unnatural given the domain. Is there a way to do Object-Oriented programming inheritance going the other way?

Robert Harvey
  • 198,589
  • 55
  • 464
  • 673
ridthyself
  • 211
  • 1
  • 7
  • 9
    "A Mammal has a lot of potential features" **No**. All mammals have a *small* set of **common** features. All canines are mammals with some additional common features (e.g. all canines have four legs, but not all mammals have four legs). – 8bittree Oct 31 '16 at 17:07
  • 4
    @8bittree Except of course that that taxonomy isn't perfect; there are exceptions; making the hierarchy imperfect. – Servy Oct 31 '16 at 17:08
  • 3
    @Servy Yes, but the point is that you don't make the root of a taxonomy or OO hierarchy describe every single *possible* feature that could exist somewhere in the taxonomy, you start with only the common features that *everything* has. – 8bittree Oct 31 '16 at 17:10
  • 4
    @gnat: I'd suggest that [Karl Bielefeldt's answer on "Is inheritance that adds rules bad?"](http://softwareengineering.stackexchange.com/a/238389/97259) makes that a better target. – jscs Oct 31 '16 at 17:16
  • 1
    @JoshCaswell you have a point here - despite "mine" dupe target being closer by discussing concrete matter of square and rectangle mentioned by OP, Karl's answer seems to make better general analysis – gnat Oct 31 '16 at 17:23
  • 1
    @8bittree, mammals have a very very small set of common features as not all have hair, not all have legs, not all have a Y chromosome, not all give birth to live young etc. And that's the problem with modelling real world systems with OO inheritance: the real world isn't nice and neat like that and your "common features that everything has" becomes vanishingly small. – David Arno Oct 31 '16 at 17:28
  • 2
    I think the other question I linked is a better dupe target: it digs into the problems of modeling real-world taxonomies using OOP inheritance. –  Oct 31 '16 at 17:31
  • 1
    @DavidArno Right, mammals are defined by their common features (however small that set may be), not by all the potential features that might show up somewhere down the tree. I wasn't trying to say that the examples here are perfect for modeling with OO inheritance, just that real world taxonomies are additive, not subtractive as the OP thinks. – 8bittree Oct 31 '16 at 17:39
  • 1
    Firstly, ask whether the class (type) is dependent on some piece of data. (Or, ask whether the class/type might change as a result of some data change.) Secondly, ask whether that piece of data is mutable. If you have both, then it needs to be modeled with a more fluid relationship than the OOP inheritance found in certain programming languages. Note that your canine example demonstrates immutability: **you can't modify a beagle into a golden retriever**. (If you interbreed them, the result is a new instance, not a modification.) Meanwhile, an employee might be promoted to supervisor some day. – rwong Oct 31 '16 at 19:48
  • 1
    This one sentence, *"Can a child (class) be defined in terms of being a more restrictive subset of its parent class rather than being defined in terms of additional features?"* can be answered: **Yes, subject to the following:** (1) The restriction is prescribed at the time of construction; (2) instances of child class is prevented from being modified into a violation of that restriction (i.e. the class invariance is enforced); (3) the software designer accepts the consequence that an instance of the parent class, though it might have been initialized with data that makes it qualify for ... – rwong Oct 31 '16 at 19:59
  • 1
    ... (3) the software designer accepts the consequence that an instance of the parent class, though it might have been initialized with data that makes it qualify for the more restrictive child class, that instance would not be treated as an instance of the child class because **that qualification wasn't being requested when the instance was constructed**. – rwong Oct 31 '16 at 20:00
  • 1
    Taxonomy doesn't suffer from the restrictions that computer programming languages imposes on OOP design. Therefore, approaching this programming problem from taxonomy point-of-view will not help you explain the problems that come from programming language implementation. – rwong Oct 31 '16 at 20:02
  • 1
    As for working around the problem, the Wikipedia article has many. If anyone has a new idea that isn't mentioned there, go ahead. – rwong Oct 31 '16 at 20:03
  • 1
    Amusingly, when people I ask me why I dislike inheritance, and large inheritance hierarchies in particular, I point them to the cluster**** that is the taxonomy of organisms. This is exactly *why* we should not try to model software entities after "real-world" models. Please don't do this. – gardenhead Nov 01 '16 at 01:07

1 Answers1

3

No no no. You're trying to make the issue about whether the root should have more or fewer traits than the child types. Guess what? No one cares!

If I am a user of mammals, I have a certain set of messages I'd like to be able to send a mammal without ripping a hole in the universe. So if I tell a mammal to fly and it turns out to be a dog it's okay for it to tilt its head and look at me funny.

The null object pattern saves us from the hole in the universe.

The traits a mammal should have are neither the traits of every subtype nor the traits common to every subtype. They are the traits needed by the client. No more. No less.

People faced with this problem often obsess on the Liskov Substitution Principle. This is a good thing to follow but the answer to the problem isn't there. It's here: Interface Segregation Principle

ISP tells you not to expose more than is needed to be used. That means neither the root nor the children have any authority in what should be exposed. The user of mammals is the one and only authority here. Everything else is clutter. Designing a taxonomy without considering how it will be used first is a recipe for disaster.

candied_orange
  • 102,279
  • 24
  • 197
  • 315
  • Interface! Of course! It seems much more logical. If a person needs a name, why have a dubious Human object when you can have an obvious Namable interface? In fact, why use inheritance at all... – ridthyself Nov 01 '16 at 17:55