73

Background:

As a Java programmer, I extensively inherit (rather: implement) from interfaces, and sometimes I design abstract base classes. However, I have never really felt the need to subclass a concrete (non-abstract) class (in the cases where I did it, it later turned out that another solution, such as delegation would have been better).

So now I'm beginning to feel that there is almost no situation where inheriting from a concrete class is appropriate. For one thing, the Liskov substitution principle (LSP) seems almost impossible to satisfy for non-trivial classes; also many other questions here seem to echo a similar opinion.

So my question:

In which situation (if any) does it actually make sense to inherit from a concrete class? Can you give a concrete, real-world example of a class that inherits from another concrete class, where you feel this is the best design given the constraints? I'b be particularly interested in examples that satisfy the LSP (or examples where satisfying LSP seems unimportant).

I mainly have a Java background, but I'm interested in examples from any language.

Community
  • 1
  • 1
sleske
  • 81,358
  • 34
  • 189
  • 227
  • 4
    When coding a hierarchy of classes, such as the trivial Dog extends Animal. I usually use inheritance extensively when coding datamodels. For me, modelling real life things is when inheritence comes to play. – Mister Smith Sep 21 '11 at 07:31
  • Assuming I got what you mean by delegation: One good reason for using subclasses is that it's such a big headache to define classes that delegate all the methods of an interface to another class - in Java and many other OOP languages too. So the common practice to accumulate more and more interfaces in classes by building a hierarchy in which each subclass implements another interface that the base class did not. Ideally, though, it makes heaps more sense to delegate interfaces. – sinelaw Sep 21 '11 at 07:31
  • 5
    There is the pathological case of inheriting from Object ... – Jens Schauder Sep 21 '11 at 07:42
  • +1 for a detailed explanation... – amod Sep 21 '11 at 09:41
  • @sinelaw: My mention of "delegation" referred to the "delegation pattern". I edited my question to include a link. – sleske Sep 21 '11 at 09:43
  • 12
    @ZJR: What makes you believe my "code reuse stats" are low? There are plenty of other ways to reuse code besides inheritance. – sleske Sep 21 '11 at 09:44
  • 1
    I've wondered the same thing. Check out the question I asked: http://stackoverflow.com/questions/3351666/why-use-inheritance-at-all – KaptajnKold Sep 21 '11 at 11:50
  • @sleske: in that case I meant the same thing. Don't you agree that Java could have made it a lot easier to delegate? If the syntax to delegate an entire interface to some instance was short, I would never use inheritance unless restricted by a library I'm using. But, as it is now, it's simply a headache to delegate when your objects are implementing many interfaces or large interfaces. – sinelaw Sep 22 '11 at 11:55
  • Related: [Why should a class be anything other than “abstract” or “final/sealed”?](http://programmers.stackexchange.com/questions/176692/why-should-a-class-be-anything-other-than-abstract-or-final-sealed) – sleske Nov 22 '12 at 10:31
  • Also related: [Is inheritance of concrete classes evil?](http://stackoverflow.com/questions/3887871/is-inheritance-of-concrete-classes-evil) – sleske Apr 11 '16 at 07:00

18 Answers18

20

You often have a skeletal implementations for an interface I. If you can offer extensibility without abstract methods (e.g. via hooks), it is preferable to have a non-abstract skeletal class because you can instantiate it.

An example would be a forwarding wrapper classes, to be able to forward to another object of a concrete class C implementing I, e.g. enabling decoration or simple code-reuse of C without having to inherit from C. You can find such an example in Effective Java item 16, favor composition over inheritance. (I do not want to post it here because of copyrights, but it is really simply forwarding all method calls of I to the wrapped implementation).

DaveFar
  • 7,078
  • 4
  • 50
  • 90
  • 9
    +1 for skeletal implementations. Without Swing's "adapter" classes (`MouseAdapter` etc) which provide NOOP implementations of many-method event listener interfaces, GUI components would be even more painful to write. – gustafc Sep 27 '11 at 17:29
  • @gustafc: Good example. Note, however, that the Swing adapter classes are `abstract`, so this example does not really address my question. – sleske Feb 22 '12 at 13:02
  • Suppose every class had to be either abstract or sealed, but a declaration of concrete inheritable class `foo` would declare both an abstract class `foo` and a sealed class `__impl_foo` which inherited `foo` but contained nothing else. Suppose further that `new foo()` would get converted to `new __impl_foo()`. Would such substitutions alter any semantics other than the Reflection name of the concrete type? – supercat Jul 29 '13 at 21:34
  • I guess not, besides reflection class names and reflection modifiers on the classes. But I fail to see any advantage. – DaveFar Jul 31 '13 at 17:15
18

I think the following is a good example when it can be appropriate:

public class LinkedHashMap<K,V>
    extends HashMap<K,V>

Another good example is inheritance of exceptions:

public class IllegalFormatPrecisionException extends IllegalFormatException
public class IllegalFormatException extends IllegalArgumentException
public class IllegalArgumentException extends RuntimeException
public class RuntimeException extends Exception
public class Exception extends Throwable
Andrey
  • 6,526
  • 3
  • 39
  • 58
  • 6
    Inheritance of Exceptions is indeed a good point. As to HashMap/LinkedHashMap: Why do you feel this is a good example? Would it not have been cleaner to let both inherit from an interface/abstract class? – sleske Sep 21 '11 at 13:00
  • 1
    @sleske In my mind it is absolutely legitimately to say that LinkedHashMap is a HashMap (in terms of LSP). Also I don't see any real benefits of introducing additional abstraction level here. Anyway in this particular case that inheritance is more just implementation details. It is not important for consumer that LinkedHashMap extends HashMap (you would code Map map = new LinkedHashMap rather than HashMap map = new LinkedHashMap). – Andrey Sep 21 '11 at 14:18
  • One benefit of having AbstractHashMap with subclasses LinkedHM and HM would be that you could also replace LinkedHM with HM, not just the other way around. Of course, if you always use Map anyway, it's a moot point. – sleske Sep 26 '11 at 08:16
14

One very common case I can think of is to derive from basic UI controls, such as forms, textboxes, comboboxes, etc. They are complete, concrete, and well able to stand on their own; however, most of them are also very basic, and sometimes their default behavior isn't what you want. Virtually nobody, for instance, would use an instance of an unadulterated Form, unless possibly they were creating an entirely dynamic UI layer.

For example, in a piece of software I wrote that recently reached relative maturity (meaning I ran out of time to focus primarily on developing it :) ), I found I needed to add "lazy loading" capability to ComboBoxes, so it wouldn't take 50 years (in computer years) for the first window to load. I also needed the ability to automatically filter the available options in one ComboBox based on what was shown in another, and lastly I needed a way to "mirror" one ComboBox's value in another editable control, and make a change in one control happen to the other as well. So, I extended the basic ComboBox to give it these extra features, and created two new types: LazyComboBox, and then further, MirroringComboBox. Both are based on the totally serviceable, concrete ComboBox control, just overriding some behaviors and adding a couple others. They're not very loosely-coupled and therefore not too SOLID, but the added functionality is generic enough that if I had to, I could rewrite either of these classes from scratch to do the same job, possibly better.

KeithS
  • 70,210
  • 21
  • 112
  • 164
12

Generally speaking, the only time I derive from concrete classes is when they're in the framework. Deriving from Applet or JApplet being the trivial example.

7

This is an example of a current implementation that I'm undertaking.

In OAuth 2 environment, since the documentation is still in draft stage, the specification keeps changing (as of time of writing, we're in version 21).

Thus, I had to extend my concrete AccessToken class to accommodate the different access tokens.

In earlier draft, there was no token_type field set, so the actual access token is as follows:

public class AccessToken extends OAuthToken {

    /**
     * 
     */
    private static final long serialVersionUID = -4419729971477912556L;
    private String accessToken;
    private String refreshToken;
    private Map<String, String> additionalParameters;

    //Getters and setters are here
}

Now, with Access tokens that returns token_type, I have

public class TokenTypedAccessToken extends AccessToken {

    private String tokenType;
    //Getter and setter are here...
}

So, I can return both and the end user is none the wiser. :-)

In Summary: If you want a customized class that has the same functionality of your concrete class without changing the structure of the concrete class, I suggest extending the concrete class.

Buhake Sindi
  • 87,898
  • 29
  • 167
  • 228
6

Other use case would be the to override the default behavior:

Lets say there is a class which uses standard Jaxb parser for parsing

public class Util{

    public void mainOperaiton(){..}
    protected MyDataStructure parse(){
        //standard Jaxb code 
    }
} 

Now say I want to use some different binding (Say XMLBean) for the parsing operation,

public class MyUtil extends Util{

    protected MyDataStructure parse(){
      //XmlBean code code 
    }
}

Now I can use the new binding with code reuse of super class.

shA.t
  • 16,580
  • 5
  • 54
  • 111
Santosh
  • 17,667
  • 4
  • 54
  • 79
  • 2
    Good point. Of course, here inheritance is necessary only because the base class foolishly neglects to use dependency injection for the parser... – sleske Sep 21 '11 at 13:01
  • 2
    More generally, this is the case the OP stated: "...another solution, such as delegation would have been better." – Ben Sep 21 '11 at 18:53
  • 1
    I agree with Ben and Sleske, this is a typical case where DI would be a much better solution than inheritance. You're using inheritance here solely for code reuse. – Sverre Rabbelier Sep 27 '11 at 11:00
  • I agree with @SverreRabbelier, this looks like using inheritance for code reuse, unless I'm missing something inherent to JAXB and XMLBean which I don't know well. Is there a good reason why it must be the JAXB util class that has the common logic and is extended by the XMLBean util class, or could it easily have been the other way around ? If it's the latter, to me it always means that I should not have one of the two extend the other one but have an abstract base class with the common logic and have both the util classes extend that. – SantiBailors Apr 11 '16 at 12:28
6

I mainly have a Java background, but I'm interested in examples from any language.

Like many frameworks, ASP.NET makes heavy use of inheritance to share behaviour between classes. For example, HtmlInputPassword has this inheritance hierarchy:

System.Object
  System.Web.UI.Control
    System.Web.UI.HtmlControls.HtmlControl          // abstract
      System.Web.UI.HtmlControls.HtmlInputControl   // abstract
        System.Web.UI.HtmlControls.HtmlInputText
          System.Web.UI.HtmlControls.HtmlInputPassword

in which can be seen examples of concrete classes being derived from.

If you're building a framework - and you're sure you want to do that - you may well finding yourself wanting a nice big inheritance hierarchy.

AakashM
  • 62,551
  • 17
  • 151
  • 186
4

The decorator pattern, a handy way of adding additional behaviour to a class without making it too general, makes heavy use of inheritance of concrete classes. It was mentioned here already, but under somewhat a scientific name of "forwarding wrapper class".

MaDa
  • 10,511
  • 9
  • 46
  • 84
3

Lot of answers but I though I'd add my own $0.02.

I override concreate classes infrequently but under some specific circumstances. At least 1 has already been mentioned when framework classes are designed to be extended. 2 additional ones come to mind with some examples:

1) If I want to tweak the behavior of a concrete class. Sometimes I want to change how the concrete class works or I want to know when a certain method is called so I can trigger something. Often concrete classes will define a hook method whose sole usage is for subclasses to override the method.

Example: We overrode MBeanExporter because we need to be able to unregister a JMX bean:

public class MBeanRegistrationSupport {
    // the concrete class has a hook defined
    protected void onRegister(ObjectName objectName) {
    }

Our class:

public class UnregisterableMBeanExporter extends MBeanExporter {
    @Override
    protected void onUnregister(ObjectName name) {
        // always a good idea
        super.onRegister(name);
        objectMap.remove(name);
    }

Here's another good example. LinkedHashMap is designed to have its removeEldestEntry method overridden.

private static class LimitedLinkedHashMap<K, V> extends LinkedHashMap<K, V> {
    @Override
    protected boolean removeEldestEntry(Entry<K, V> eldest) {
        return size() > 1000;
    }

2) If a class shares a significant amount of overlap with the concrete class except for some tweaks to functionality.

Example: My ORMLite project handles persisting Long object fields and long primitive fields. Both have almost the identical definition. LongObjectType provides all of the methods that describe how the database deals with long fields.

public class LongObjectType {
    // a whole bunch of methods

while LongType overrides LongObjectType and only tweaks a single method to say that handles primitives.

public class LongType extends LongObjectType {
    ...
    @Override
    public boolean isPrimitive() {
        return true;
    }
}

Hope this helps.

Gray
  • 115,027
  • 24
  • 293
  • 354
  • About 1): Yes, providing hook methods for overriding is a well-known pattern. However, I feel that dependency injection (or using aspects) is superior, and usually the better alternative. Of course, if you're stuck with a class with a hook method, you must live with it. – sleske Sep 28 '11 at 07:25
  • About 2): There I would really have created one abstract class, and two implementations. I feel this also better reflects the relationship of the classes (common base functionality, applied in two different ways). Also, this is more robust if later LongObjectType needs new methods. If you put them into the abstract top class, you cannot forget to override them in both subclasses. With the "LongType extends LongObjectType" version, you could add to LongObjectType and forget to override in LongType. – sleske Sep 28 '11 at 07:28
  • About 1): Dependency injection is fine when it is supported by the base class. Again, these are currently implemented classes that I'm talking about. I really dislike AOP. It's incredibly hard to debug and certainly _much_ less obvious from an architecture standpoint. – Gray Sep 28 '11 at 12:30
  • About 2): Certainly there are cases where I would use abstract classes but this just doesn't seem right. Really there is a `BaseDataType` that I didn't describe that sets `isPrimitive()` to be false. The `LongObjectType` subclass then describes how to persist longs and `LongType` overrides the `isPrimitive()` to return true. Having a `BaseLongObjectType` just seems extraneous to me. – Gray Sep 28 '11 at 12:37
2
  1. Inheriting concrete class is only option if you want to extend side-library functionality.

  2. For example of real life usage you can look at hierarchy of DataInputStream, that implements DataInput interface for FilterInputStream.

Yarg
  • 5,586
  • 2
  • 17
  • 22
2

I'm beginning to feel that there is almost no situation where inheriting from a concrete class is appropriate.

This is one 'almost'. Try writing an without extending Applet or JApplet.

Here is an e.g. from the applet info. page.

/* <!-- Defines the applet element used by the appletviewer. -->
<applet code='HelloWorld' width='200' height='100'></applet> */
import javax.swing.*;

/** An 'Hello World' Swing based applet.

To compile and launch:
prompt> javac HelloWorld.java
prompt> appletviewer HelloWorld.java  */
public class HelloWorld extends JApplet {

    public void init() {
        // Swing operations need to be performed on the EDT.
        // The Runnable/invokeLater() ensures that happens.
        Runnable r = new Runnable() {
            public void run() {
                // the crux of this simple applet
                getContentPane().add( new JLabel("Hello World!") );
            }
        };
        SwingUtilities.invokeLater(r);
    }
}
Community
  • 1
  • 1
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
2

Another good example would be data storage types. To give a precise example: a red-black tree is a more specific binary tree, but retrieving data and other information like size can be handled identical. Of course, a good library should have that already implemented but sometimes you have to add specific data types for your problem.

I am currently developing an application which calculates matrices for the users. The user can provide settings to influence the calculation. There are several types of matrices that can be calculated, but there is a clear similarity, especially in the configurability: matrix A can use all the settings of matrix B but has additional parameters which can be used. In that case, I inherited from the ConfigObjectB for my ConfigObjectA and it works pretty good.

2

In general, it is better to inherit from an abstract class than from a concrete class. A concrete class must provide a definition for its data representation, and some subclasses will need a different representation. Since an abstract class does not have to provide a data representation, future subclasses can use any representation without fear of conflicting with the one that they inherited. Even i never found a situation where i felt concrete inheritence is neccessary. But there could be some situations for concrete inheritence specially when you are providing backward compatibility to your software. In that case u might have specialized a class A but you want it to be concrete as your older application might be using it.

amod
  • 4,190
  • 10
  • 49
  • 75
2

Your concerns are also echoed in the classic principle "favor composition over inheritance", for the reasons you stated. I can't remember the last time I inherited from a concrete class. Any common code that needs to be reused by child classes almost always needs to declare abstract interfaces for those classes. In this order I try to prefer the following strategies:

  1. Composition (no inheritance)
  2. Interface
  3. Abstract Class

Inheriting from a concrete class really isn't ever a good idea.

[EDIT] I'll qualify this statement by saying I don't see a good use case for it when you have control over the architecture. Of course when using an API that expects it, whaddaya gonna do? But I don't understand the design choices made by those APIs. The calling class should always be able to declare and use an abstraction according to the Dependency Inversion Principle. If a child class has additional interfaces to be consumed you'd either have to violate DIP or do some ugly casting to get at those interfaces.

Dave Sims
  • 5,060
  • 3
  • 24
  • 26
1

from the gdata project:

com.google.gdata.client.Service is designed to act as a base class that can be customized for specific types of GData services.

Service javadoc:

The Service class represents a client connection to a GData service. It encapsulates all protocol-level interactions with the GData server and acts as a helper class for higher level entities (feeds, entries, etc) that invoke operations on the server and process their results.

This class provides the base level common functionality required to access any GData service. It is also designed to act as a base class that can be customized for specific types of GData services. Examples of supported customizations include:

Authentication - implementing a custom authentication mechanism for services that require authentication and use something other than HTTP basic or digest authentication.

Extensions - define expected extensions for feed, entry, and other types associated with a the service.

Formats - define additional custom resource representations that might be consumed or produced by the service and client side parsers and generators to handle them.

sleske
  • 81,358
  • 34
  • 189
  • 227
swanliu
  • 781
  • 3
  • 8
  • Good example. To me, however, this class looks like it should be abstract. It even has a constructor with default visibility, meaning you can only invoke it from within the same package, thus to use it from the outside you *must* subclass it anyway. – sleske Sep 28 '11 at 07:21
0

Just a general thought. Abstract classes are missing something. It makes sense if this, what is missing, is different in each derived class. But you may have a case where you don't want to modify a class but just want to add something. To avoid duplication of code you would inherit. And if you need both classes it would be inheritance from a concrete class.

So my answer would be: In all cases where you really only want to add something. Maybe this just doesn't happen very often.

NoDataDumpNoContribution
  • 10,591
  • 9
  • 64
  • 104
0

I find the java collection classes as a very good example. So you have an AbstractCollection with childs like AbstractList, AbstractSet, AbstractQueue... I think this hierarchy has been well designed.. and just to ensure there's no explosion there's the Collections class with all its inner static classes.

Scorpion
  • 3,938
  • 24
  • 37
  • That is just my point: The class hierarchy of the java collection classes use *abstract* classes (AbstractCollection,AbstractList etc.). I was interested in inheritance from *concrete* classes. – sleske Sep 21 '11 at 10:52
  • Oh come on, didn't you notice that these abstract classes are indeed implemented (ArrayList, HashSet) within the java collection API itself. There are quite a few implementations of these abstract classes which form the back bone. – Scorpion Sep 21 '11 at 11:26
  • Erm, I'm afraid I can't follow you. Yes, the abstract base classes have concrete subclasses in den API. But that was not my question. My question was about *inheriting from a concrete class*, which only very few of the Collection classes do. – sleske Sep 21 '11 at 12:55
  • As a matter of fact, the only collection classes I could find which subclass a concrete class are LinkedHashSet ( – sleske Sep 21 '11 at 12:58
  • oh, I misread your question to "inheriting from classes" and thereby missed out on noticing that inheriting from concrete classes is not what you are looking at. Inheriting from concrete classes has a very limited scope, if any, and I am not surprised that there are very few instances and those that are, are quite debatable. – Scorpion Sep 21 '11 at 13:33
0

You do that for instance in GUI libraries. It makes not much sense to inherit from a mere Component and delegate to a Panel. It is likely much easyer to inherit from the Panel directly.

Angel O'Sphere
  • 2,642
  • 20
  • 18