Inheritance using non-abstract base class

This post is based on the question https://stackoverflow.com/questions/49002/prefer-composition-over-inheritance/11758048#comment15634305_11758048.

Some people said – check whether there is “is-a” relationship. If it is there use inheritance. What I think is there should be a second check for using inheritance. Use inheritance only if the base class is abstract. If the base class need to be instantiated then use composition; not inheritance.

E.g 1. Accountant is an Employee. But I will not use inheritance because a Employee object can be instantiated. (When you talk to business people, they will tell you – Accountant is an Employee. But in OO world Accountant is not (should not be) an employee)

E.g 2. Book is a SellingItem. A SellingItem cannot be instantiated – it is abstract concept. Hence I will use inheritance. The SellingItem is an abstract base class (or interface in C#)

What I am looking for here is an example that will challenge my argument –that is a scenario in which inheritance is better than composition even though the base class is non-abstract (base class can be instantiated). Can you please provide such an example?

Note: It would be more helpful if you can provide a scenario based on Bank domain, HR domain, Retail domain or any other popular domain.

Note: In the design, please assume that we have full control of the code. That is we are not using any external API. Also we are starting from beginning.

I will mark as answered if there is an example that explains a scenario that proves my argument is wrong. It is not a mere discussion on whether to use Composition or Inheritance.

I support @anon answer in https://stackoverflow.com/questions/3351666/why-use-inheritance-at-all?lq=1

The main reason for using inheritance is not as a form of composition – it is so you can get polymorphic behaviour. If you don’t need polymorphism, you probably should not be using inheritance.

@MatthieuM. says in Code Smell: Inheritance Abuse

The issue with inheritance is that it can be used for two orthogonal purposes:

interface (for polymorphism)

implementation (for code reuse)

REFERENCE

  1. Employee- Accountant Example https://stackoverflow.com/questions/11759120/issue-in-using-composition-for-is-a-relationship
  2. Selling Item Example – https://codereview.stackexchange.com/questions/14077/is-it-proper-tpt-inheritance
  3. Programming SOLID Principles
  4. Code Smell: Inheritance Abuse

8

Although you mentioned in a comment it’s not the talk about “composition vs inheritance”, I have to return to it. Because composition is better than inheritance If we assume that decoupling is always a good thing (Prefer composition to inheritance?).

Actually it is not always the case. Even if you see that “is a” can be replaced with “has a” or “has a” looks more promising, “is a” has a very nice automatic properties.

Consider any widget hierarchy. Usually everything related to dimension is buried deep at the root. And no matter how long the inheritance path, you can always directly call SetBounds of the instance and pass the instance to a procedure that expects deep base object, the compiler will accept it because from “is a” comes automatic type conversion and access.

But if you convert the inheritance hierarchy into composition hierarchy (technically it is always possible), you will lose convenience in both cases, because you should point to the concrete piece of composition tree in order to change the dimension or provide a procedure with particular class type. Compare

 MyForm.SetBounds(...  // easy because of an "is a"-tree
 MyForm.ScrollingWinControl.WinControl.Control.SetBounds  //complex because of a "has a"-tree 

or

 GetSomeInfoOfControl(MyForm) // easy ...
 GetSomeInfoOfControl(MyForm.ScrollingWinControl.WinControl.Control) //complex ...

So despite the price of stronger coupling, inheritance sometimes is much easy to manage and abstract.

2

The entire ‘is a’ vs ‘has a’ discussion never made any sense to me. There is already a good definition about when to use inheritance, so called “Liskov substitution principle”, which states:

Let q(x) be a property provable about objects x of type T. Then q(y) should be provable for objects y of type S where S is a subtype of T.

The first thing you’ll notice is, that it is generally a bad idea to let people with PhD explain a simple problem.

Second, this exactly states when to use inheritance. If I may use Wikipedia’s article and apply it to your accountant/employee example:

Liskov’s notion of a behavioral subtype defines a notion of substitutability for mutable objects; that is, if Accountant is a subtype of Employee, then objects of type Employee in a program may be replaced with objects of type Accountant without altering any of the desirable properties of that program (e.g., correctness).

The entire Principles paragraph of the Wikipedia article contains some more interesting principles.


Apparently most answers refer to LSP in one way or the other. Baqueta cleverly disguised it as a easy-to-miss-link and Geek edited his post to include LSP seconds before I posted my answer. So, LSP seems to be the most reasonable way to create your hierarachy.


Some examples of where your principle doesn’t hold:

  • bicycle and a mountain bike
  • circle and a sphere
  • A button and an image button or toggle button.

In WPF, the concrete System.Windows.Controls.Button has the following subclasses:

  • CalendarButton
  • CalendarDayButton

In Java and C#, everything extends directly or indirectly from object, which isn’t abstract.

Also in WPF: DatePickerTextBox is a subclass of (the concrete) TextBox. There are lots more examples. These respect LSP and the base class is not abstract.

As an extra note. I think the reason you found this principle is because it is generally a good idea to keep your hierarchy very flat, because inheritance introduces coupling. One or two levels deep is more than enough. Abstract classes will (almost) always be subclassed somewhere, since that is the purpose of making a class abstract, so that others can make it specialized. Most concrete classes don’t need to be specialized in any way. That may be the reason you haven’t found an example yet.

0

I think you’ve actually got there is a good rule of thumb for choosing to make a class abstract: if there are (or you can forsee the need for) variants of a class with slightly different behaviour, then it’s often a good idea to create an abstract base class.

Bottom line though, in my experience: as long as the relationship you’re dealing with is really is-a (e.g. your Accountant-Employee example is more suited to composition than inheritance, as per this answer) then it’s very rarely harmful/problematic to inherit from non-abstract classes.

A couple of examples when you might want/have to ignore your rule. Both assume you require Poodle to be substitutable for Dog:

  1. Dog is a class in an external API and there’s no IDog interface for Poodle to implement.
  2. Dog is already instantiated in dozens of different places in your (already tested) code.

Admittedly, these are both cases where a better original design might have helped, but in the real world designs are never perfect!

2

I think inheriting concrete class is OK and actually quite valuable feature.

The “is-a” rule is only good for extremely simple models and domains. The way I see it, is that classes represent behavior and encapsulate state where the state can be another class. What kind of behavior Accountant, Employee, Book and Selling item have in relation to our model? That is the question you should ask. And based on that use either inheritance of composition.

Also, many real-world object are not good examples, because they are usually composites of different behaviors, that can be shared between different real-world objects. Many animal species walk on all 4. That is good example of behavior.

Extending already existing behavior by inheritance is great way to simplify and modularise the model of the domain. And for our walk behavior example, we can extend WoundedWalk class, that does exactly what its name says.

0

I don’t think there is any necessity of a challenging example. What you say is a nice design principle which is named dependency inversion. That is, higher components should never depend on lower components. Lower components should depend on higher components only.

Like every rule, this one might have exceptions, too. But there are no rules without exceptions!

2

You use inheritance over composition when you need code reuse . Inheritance helps in evolving classes really fast . However , you should be careful not to overuse it . use it judiciously only when it makes sense (ie when you are absolutely sure that there is a “IS-A” relationship between every objects of both the classes .You need to make sure that the subclass objects respects the Liskov Substitution principle . Even then it might not be good idea everytime if you add a value component to a subclass and the super class also has the notion of a value component. From Effective Java :

There is no way to extend an instantiable class and add a value
component while preserving the equals contract, unless you are willing
to forgo the benefits of object-oriented abstraction.

On the other hand composition has multiple advantages over inheritance and so most of the times it is preferred over inheritance but that wasn’t your question. Spring’s *Dependency Injection principle * is primarily based on this premise .

0

What I am looking for here is an example that will challenge my argument

Examples abound:

  • Buttons. In many GUI frameworks, View is not an abstract class — you can and often do create vanilla views. But there are also plenty of subclasses of View, such as Button.

  • Mutable objects. Some frameworks, e.g. Cocoa, have data container classes that are immutable (NSArray, NSString, NSDictionary, etc.) and also mutable subclasses of those (NSMutableArray, NSMutableString, etc.). You can do anything to an instance of NSMutableArray that you can do to an instance of NSArray, and then some.

  • Employee. Borrowing from your Accountant example, its likely that an Employee class might be a subclass of Person, but there’s no reason that Person needs to be abstract.

  • Accountant. Your example is often given to illustrate how composition can/should be used in place of inheritance, but that doesn’t mean that composition is always the best choice in this case. Yes, you can create an accountant by separating the ‘job’ aspects from the ’employee’ and then configuring an instance of Employee with a particular job. But there may be good reasons to use inheritance instead. An accountant isn’t just an employee who happens to crunch numbers; an accountant is a particular kind of employee, and you may want to use inheritance to reflect that. For example, you might want the Accountant class to implement a ProfessionalStanding interface or to include functionality that helps detect conflicts of interest. Also, creating an Accountant class makes it possible to use the language’s type system to help prevent employees who aren’t accountants from being used in roles where only an accountant should be used: Project::addAuditor(Accountant& a);

The decision to use or not use inheritance has little to do with whether a class is abstract. It’s the other way around, actually: abstract classes are used to force you to create a subclass, generally to ensure that important missing functionality is provided. The fact that you can instantiate a class certainly doesn’t mean that you should avoid subclassing.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật