I have been writing code since 1980. In 1999, I learned Java and after discovering IntelliJ the love was complete. XML and XSLT was a revelation in 2000, too bad the standards committees have done so much damage since. Contributed to the Flying Saucer open source XML and CSS rendered and published an open source XSLT generator, weffo. Currently employed by Google. Torbjörn is a DZone MVB and is not an employee of DZone and has posted 9 posts at DZone. You can read more from them at their website. View Full User Profile

The Legacy of Inheritance

08.20.2008
| 5226 views |
  • submit to reddit
Is inheritance really useful or is it a feature that causes more problems than it solves? Certainly I can't think of a case where I've been really grateful that I've been able to inherit from a superclass but I can think of several instances where it has caused friction and where the extension mechanism of inheritance tended to lead the programmer the wrong way.
Consider the following code (public fields for brevity):

public class Square {
  public int base;
  public int getArea() {
return base * base;
 }
}

public class Rectangle extends Square {
  public int height;
  @Override public int getArea() {
    return base * height;
  }
}

public class Parallelogram extends Rectangle {
  public double angle;
}

Now how do we implement a Rhombus? Is it a Square extended with an angle (and overridden area calculation) or a Parallelogram with conditions on setting the properties so that the invariant is preserved (which is why we should have accessors, by the way)?
Well, the correct answer is neither, even though we have a nice sequence of extensions. The problem is that we have been led astray by the extension mechanism and violated the "is a" rule for subclassing and ended up with a corrupt type system. Clearly a Parallelogram is not a Rectangle which equally clearly is not a Square so a subclass instance may not safely be used in place of a superclass instance. Reversing the class hierarchy solves the issue, however it creates subclasses that are restrictions of the superclass rather than extensions.
An acquaintance of mine who is highly experienced in creating standardized components for information interchange once claimed that it only works to inherit properties by restriction. This is well worth considering, although I'm not entirely convinced because it causes a different set of problems when restriction means "that particular property is not used", as it so often does in information interchange scenarios. In that case it is usually not interesting nor useful to know what the superclass is. In our case at hand it will work because the subclasses actually have a meaningful and useful value of the property but it is restricted by an invariant, so it is also useful to be able to view them as instances of the superclass.
Let's try coding again:
public class Parallelogram {
  protected int base;
  protected int height;
  protected double angle;

  public void setAngle(double angle) {
    this.angle = angle;
}
}

public class Rectangle extends Parallelogram {
  @Override public void setAngle(double angle) {
     // What should we do here?
  }
}
...

Oops, this doesn't seem to work well, either. Obviously we can't just inherit the setAngle method or we could end up with a corrupt Rectangle, nor is there any reasonable action we can take. We can get out of our pickle, however, because constructors are not inherited! Simply make our instances immutable:
public class Parallelogram {
  public final int base;
  public final int height;
  public final int angle;

  public Parallelogram(int base, int height, double angle) {
    this.base = base;
    this.height = height;
    this.angle = angle;
  }

  public int getArea() {
    return base * height;
  }
}

public class Rectangle extends Parallelogram {
  public Rectangle(int base, int height) {
    super(base, height, Math.PI/2);
}
}

public class Square extends Rectangle {
  public Square(int side) {
    super(side, side);
  }
}

That seems to work, and the implementation of getArea() is actually profitably inherited. But we still have a problem in Java with a Rhombus, since a Square is both a Rectangle and a Rhombus but a Rhombus is not a Rectangle. To solve that would require defining the types as interfaces and have separate implementation classes (now I understand why that is often  recommended :-) ).
If we had chosen to implement Parallelogram with a field for the length of the side instead of the height, the formula for the area would have been base*Math.sin(angle)*side. Even if this would have worked for our Rectangle, it would have been inefficient (although when the fields are immutable it could probably be optimized by the compiler and/or JVM).
On the whole, I believe it is seldom profitable to inherit the implementation of a method, if you have a good example to the contrary, please share it.
I think that overriding all public methods would be preferable, even if you just decide to call super's version, at least it would show that you gave some thought to whether it was correct or not. Without having done an exhaustive study, I believe this is especially true for interfaces that indicate that a class "is" something rather than that it "is a" something, i.e. those interfaces whose name usually end in "able". Try Cloneable, Externalizable, Runnable and Printable.From http://tobega.blogspot.com/2008/08/legacy-of-inheritance.html
Published at DZone with permission of Torbjörn Gannholm, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags:

Comments

Brian Sayatovic replied on Wed, 2008/08/20 - 8:21am

Geometrically speaking, there are IS-A relationships, with quadrilateral being the most basic, followed by trapezoid, parallelagram, rhombus/rectangle, and square.  But when we speak of these geometrically, we talk only about observing their properties.

Your code above shows mutable classes.  We don't often see a square on a piece of paper and then chose to warp it.  The gemoetrically observable inheritence of their qualities only holds so long as you don't morph the shapes.  If your classes were immutable, wouldn't that solve much of your problem?

	public class Quadrilateral {
		// ...
	}
	
	public class Trapezoid extends Quadrilateral {
		// ...
	}
	
	public class Parallelogram extends Trapezoid {
		private int a;
		private int b;
		private float angle;
		public Parallelogram(int pA, int pB, float pAngle) {
			...
		}
	}
	
	public class Rhombus extends Parallelogram {
		public Rhobus(int pSide, float pAngle) {
			super(pSide, pSide, pAngle);
		}
	}
	
	public class Square extends Rhombus {
		public Square(int pSide) {
			super(pSide, 90);
		}
	}

Thomas Mueller replied on Wed, 2008/08/20 - 9:23am

I believe it is seldom profitable to inherit the implementation of a method, if you have a good example to the contrary, please share it.

Ever heard of java.lang.Object, java.io.InputStream? :-) Just search for "extends" in any good software.

Doug McCreary replied on Wed, 2008/08/20 - 11:42am

I've long thought that inheritance is just a poorly chosen, inflexible sort of syntactic anti-sugar for interface delegation. 

mark taylor replied on Wed, 2008/08/20 - 2:38pm

It's interesting how people rediscover this every so often. The issue is: inheritance is not subtyping. It's a subtle, but important distinction. It's been studied extensively by programming language researchers.

 

http://www.amazon.com/Foundations-Object-Oriented-Languages-Types-Semantics/dp/026202523X/

 

 

Steven Baker replied on Wed, 2008/08/20 - 8:09pm

your just using it wrong

either learn proper OO or go back to your C

Artur Biesiadowski replied on Thu, 2008/08/21 - 6:22am

On my university, there was a teacher who got it even more wrong. In one of the exercises class Point was given (with x,y inside) and then Line extended it (adding x1,y1) and then Triangle was inherting from Line (adding x2,y2)... Circle was also extending Point (with radius added). Then, shape of circle + triangle together was created by multiple inheritance (it was c++ code).

He was not teaching me, but my younger friend - I had to explain afterward to that friend that inheritance is not THAT stupid and there are ways to use it properly...

Jason Marshall replied on Thu, 2008/08/21 - 1:08pm

Reversing the class hierarchy solves the issue, however it creates subclasses that are restrictions of the superclass rather than extensions.

I beg pardon, but if you study type theory a bit more, I think you'll find that all subtypes are in fact restrictions on their supertypes.  A supertype is an abstract concept, like a 'mammal'.  Some mammals can fly.  Some can hold their breath for hours at a time.  But there is no mammal that can do both.

Most people I run into who have serious, deep problems comprehending generics have this same failure of reasoning.  They're used to subclassing to 'add things' to a type, which is exactly how most of us code.  When you add a function to one subclass, you're in a way saying none of its siblings have/need this functionality (otherwise, you would have put it in the base class, right?).  In essence, you're carving out territory for this class at the expense of its peers.

 

 

 

 

Torbjörn Gannholm replied on Sat, 2008/08/23 - 1:56pm in response to: Thomas Mueller

[quote=thomasmueller]
I believe it is seldom profitable to inherit theimplementation of a method, if you have a good example to the contrary,please share it.

Ever heard of java.lang.Object, java.io.InputStream? :-) Just search for "extends" in any good software.

[/quote]

 How do you logically deduce that the presence of the extends word signifies successful inheritance of implementation? Without overriding the methods, the subclass would be useless, n'est-ce pas? 

Steven Baker replied on Sat, 2008/08/23 - 8:44pm

the subclass isnt useless if u dont override methods.

your extending the class to provide more or modified functionality 

Rick Siskey replied on Thu, 2011/10/27 - 12:11am

Inheritance huh?! I thought you were referring to inheretance that discusses about wealth from someone that is passed to you. Instead, I get this very high tech and very computer-related stuff. - Rick Siskey

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.