Any good examples of inheritance from a particular class?

Background:

As a Java programmer, I widely inherit (but rather: implement) from interfaces, and sometimes create abstract base classes. However, I never felt the need to subclass a specific (non-abstract) class (in the cases when I did this, it later turned out that another solution, such as delegation , would be better).

So, now I'm starting to feel that there is practically no situation where to inherit from a particular class. First, for nontrivial classes, it is almost impossible to satisfy the principle of substitution "nofollow noreferrer">. also many other questions seem to reflect a similar view.

So my question is:

In what situation (if any) does it really make sense to inherit from a particular class? Can you give a concrete, real-life example of a class that inherits from another specific class, where you feel that this is the best design given the constraints? I am particularly interested in examples that satisfy the LSP (or examples where the implementation of the LSP seems inconsequential).

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

+72
java inheritance design oop lsp
Sep 21 '11 at 7:22
source share
18 answers

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

An example is the forwarder shell classes , in order to be able to forward another object of a particular class C that implements I , for example. enabling decoration or simply reusing C code without C -level inheritance. You can find such an example in Effective Java , paragraph 16, to approve composition over inheritance. (I donโ€™t want to publish it here because of copyright, but actually just redirects all calls of methods I to the wrapped implementation).

+20
Sep 21 2018-11-11T00:
source share

I think the following example is a good example when this may be appropriate:

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

Another good example is exception inheritance:

 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 
+18
Sep 21 2018-11-11T00:
source share

One very common case that I can think of is to work out the basic elements of the user interface, such as forms, text fields, drop-down lists, etc. They are complete, concrete and well-placed to stand on their own; however, most of them are also very simple, and sometimes their default behavior is not what you want. Virtually no one, for example, would use an instance of an unconfirmed form, unless they created a fully dynamic user interface layer.

For example, in the software part, I wrote that I had recently reached relative maturity (that is, I did not have enough time to focus primarily on its development :)), I found that I needed to add a "lazy load" to ComboBoxes, so for the first window to download it will not take 50 years (in computer years). I also needed the ability to automatically filter available parameters in one ComboBox based on what was shown in another, and finally, I needed a way to โ€œmirrorโ€ one ComboBox value in another editable control and make changes to one control of the other as well. So, I expanded the base ComboBox to provide it with additional features, and created two new types: LazyComboBox, and then MirroringComboBox. Both are based on a fully functional specific ComboBox control, simply overriding some behaviors and adding a couple others. They are not very loosely coupled and therefore not too SOLID, but the added functionality is universal enough, and if I had to do this, I could rewrite any of these classes from scratch to do the same job, perhaps better.

+14
Sep 21 '11 at 14:37
source share

Generally speaking, the only time I get from specific classes is when they are in the framework. The output from an Applet or JApplet is a trivial example.

+12
Sep 21 2018-11-11T00:
source share

This is an example of the current implementation that I am taking.

In OAuth 2, since the documentation is still under development, the specification continues to change (we are in version 21 from the moment of writing).

Thus, I had to expand my specific AccessToken class to accommodate various access tokens.

There was no token_type field set in the previous draft, so the actual access token looks like this:

 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, using access tokens that return 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 will not become wiser. :-)

In summary: If you want a custom class to have the same functionality of your particular class without changing the structure of a particular class, I suggest extending the specific class.

+7
Sep 21 '11 at 7:30
source share

Another use case would be to override the default behavior:

Suppose there is a class that uses the standard Jaxb parser for parsing

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

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

 public class MyUtil extends Util{ protected MyDataStructure parse(){ //XmlBean code code } } 

Now I can use the new superclass code reuse binding.

+6
Sep 21 '11 at 7:45
source share

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

Like many frameworks, ASP.NET makes heavy use of inheritance to share behavior 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 you can see examples of specific classes derived from.

If you create a framework - and you are sure that you want to do this, you may well find yourself the desired good inheritance hierarchy.

+6
Sep 21 '11 at 10:21
source share

decorator pattern , a convenient way to add additional behavior to a class without making it too general, makes extensive use of the inheritance of specific classes. It has already been mentioned, but under some scientific name "forwarder class".

+4
Sep 21 '11 at 11:00
source share

Lots of answers, but I would add my own $ 0.02.

I rarely redefine classes, but under certain circumstances. At least 1 has already been mentioned when class frameworks are intended to be extended. Two further examples are provided:

1) If I want to customize the behavior of a particular class. Sometimes I want to change how a particular class works, or I want to know when some method is called, so I can call something. Often, specific classes define a hook method, the only use of which for subclasses overrides the method.

Example: we redefined MBeanExporter because we need to be able to unregister the 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 is another good example. LinkedHashMap designed to override the removeEldestEntry method.

 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 number of overlaps with a specific class, with the exception of some settings for functionality.

Example: My ORMLite project processes persistent fields of Long and Long objects primitive fields. Both have an almost identical definition. LongObjectType contains all 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 modifies one method to say that it processes primitives.

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

Hope this helps.

+3
Sep 27 '11 at 17:28
source share
  • Inheriting a specific class is only an option if you want to extend the functions of the side library.

  • For example, using real life, you can look at the DataInputStream hierarchy, which implements the DataInput interface for FilterInputStream.

+2
Sep 21 2018-11-11T00:
source share

I begin to feel that there is practically no situation where it is advisable to inherit from a particular class.

This one is "almost." Try writing an applet without the Applet or JApplet .

Here, for example, from an applet. 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); } } 
+2
Sep 21 '11 at 7:45
source share

Another good example would be data storage types. To give an exact example: a red-black tree is a more specific binary tree, but receiving data and other information, such as size, can be handled the same way. Of course, a good library should have one already implemented, but sometimes you have to add certain types of data for your problem.

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

+2
Sep 21 2018-11-11T00:
source share

In general, it is better to inherit from an abstract class than from a specific class. A particular class must provide a definition to represent its data, and some subclasses need a different representation. Since an abstract class should not provide a representation of the data, future subclasses can use any representation without fear of conflict with the one they inherited. Even I never found a situation where I felt that specific inheritance was needed. But specific situations for a specific inheritance may arise specifically when you provide backward compatibility with your software. In this case, u might specialize in class A , but you want it to be specific, since your older application could use it.

+2
Sep 21 2018-11-11T00: 00Z
source share

Your concerns are also reflected in the classic principle of โ€œ approve composition over inheritance โ€ for the reasons you have indicated. I canโ€™t remember the last time I inherited from a particular class. Any generic code that needs to be reused by child classes should almost always declare abstract interfaces for these classes. In this order, I prefer the following strategies:

  • Composition (without inheritance)
  • Interface
  • Abstract class

Inheriting from a particular class is indeed not always a good idea.

[EDIT] I will qualify this statement by saying that I do not see this as a good use case when you control the architecture. Of course, when using the API that this expects, whaddaya will do? But I do not understand the design choices made by these APIs. The calling class should always be able to declare and use abstraction in accordance with the Dependency Inversion Principle . If the child class has additional interfaces to use, you will either have to break the DIP, or do an ugly cast to gain access to these interfaces.

+2
Sep 27 '11 at 17:33
source share

from the gdata project:

com.google.gdata.client.Service is intended to be used as a base class that can be customized for certain types of GData Services.

Javadoc service:

The Service class is a client connection to the GData service. It encapsulates all interactions at the protocol level with the GData server and acts as an auxiliary class for objects of a higher level (feeds, records, etc.), which cause operations on the server and process their results.

This class provides the basic basic functionality needed to access any GData service. It is also intended to be used as a base class that can be configured for certain types of GData services. Examples of supported settings:

Authentication is the implementation of a custom authentication mechanism for services that require authentication and the use of something other than basic or digest authentication HTTP.

Extensions - define the expected extensions for channels, records and other types associated with the service.

Formats - define additional user representations of resources that can be used or created by parsers and generators on the client side and on the client side for their processing.

+1
Sep 21 '11 at 7:45
source share

I believe java collection classes are a very good example. So you have an AbstractCollection with children like AbstractList, AbstractSet, AbstractQueue ... I think this hierarchy is well designed .. and just so that there is no explosion there of the Collections class with all its internal static classes.

0
Sep 21 2018-11-11T00:
source share

You do this, for example, in GUI libraries. It makes no sense to inherit from a simple component and delegate it to the group. Most likely, itโ€™s much easier to inherit from Panel directly.

0
Sep 21 2018-11-11T00:
source share

Just a general thought. Abstract classes are missing something. It makes sense if this, which is missing, is different in each derived class. But you may have a case where you do not want to change the class, but just want to add something. To avoid code duplication, you inherit. And if you need both classes, it will inherit from a particular class.

So, I would answer: in all cases when you really want to add something. Perhaps this happens infrequently.

0
May 24 '13 at 7:52
source share



All Articles