Register to get access to free programming courses with interactive exercises

Composition instead of inheritance JS: Dive into Classes

Inheritance is one of the most controversial OOP mechanisms. The more we learn about it, the more pitfalls we encounter.

In the previous lessons, all we did was rethink our work with classes. Inheritance adds too many new concepts and behaviors to the code. But that is not the only problem because inheritance also has fundamental flaws.

The problem with hierarchies is that our world is not hierarchical. Each classification leans on an attribute, that is important for us at a particular time. The same classification becomes useless if we add another attribute.

You can see this in online stores with sophisticated filters for selecting goods: grouping by manufacturer, field of application, child safety, and so on. Every situation will have its structure.

Take the concept of a user. Educational articles on inheritance often show user hierarchies, giving developers the impression that this is how the world works.

Now we will try to figure out what characteristics we can use to build a hierarchy of users:

  • By gender (MaleUser, FemaleUser)
  • Based on authentication (User, Guest)
  • By role (Admin, Member)
  • By type of job (Marketer, SalesManager, Programmer, Tester, Player)
  • By group (UserFromCanada, UserWhoLikesTennis)
  • By source (UserFromFacebook, UserFromGithub)
  • By type of storage (SQLUser, LocalStorageUser)

All of this can and will occur within a single program. We may need different representations for different tasks. Inheritance does not give us that freedom; it locks us into a specific unchangeable structure.

The only way out of this paradigm is more inheritance. As a result, we end up with a combination of all the possible behaviors we will encounter in the program - hierarchies with dozens or hundreds of classes. And remember that all of this must somehow coordinate with the interfaces, which can extend each other.

The solution might have been multiple inheritances. But as the life of some languages (C++) has shown, it makes things even more complicated, so everyone rejected it at the earliest opportunity.

Eventually, developers formed a common position on inheritance: composition instead of inheritance. If you try to Google this phrase, you will see many articles on the subject.

We already studied this approach in the JS: Polymorphism course. It boils down to a more competitive division of responsibilities in the application, and the delegation of functionality to other objects as needed in specific situations.

It is where the difficulties begin. Most articles about the subject give incorrect or artificial examples, so they provide no insight. First, let's separate the two different reasons for using inheritance. One is related to the direct purpose of inheritance, and the other arises from a misunderstanding of the principles of code organization.

Misuse

A prime example of the misuse of inheritance is the mixing of different levels of abstraction. Above we had an example of users divided by storage type — SQLUser. So how is the user, in terms of our domain, related to the technical aspects of storing these users? The user is not related in any way, such code shouldn't exist as a rule, and inheritance is not intended for it.

Such code arises not from ignorance of OOP, but from a misunderstanding of the general principles of code organization and the construction of abstractions. This topic is not specific to OOP, but OOP makes it more difficult because of the large number of new entities it introduces. <!---Be sure to read this article, which sheds some light on architecture.-->.

The paradox is that "composition over inheritance" refers to this very use of inheritance. In other words, the problem is not inheritance per se. It has proven to be a convenient way to organize code for those who don't know how to structure it well and do not know what abstraction barriers and application layers are.

Intended Use

The need for class inheritance arises when classes are related by code (this is not a subtype relationship). In this situation, we need an alternative to inheritance.

The solution to this problem has been known for a long time, and it's called mixins. They are a great alternative to the proper use of inheritance.


Are there any more questions? Ask them in the Discussion section.

The Hexlet support team or other students will answer you.

For full access to the course you need a professional subscription.

A professional subscription will give you full access to all Hexlet courses, projects and lifetime access to the theory of lessons learned. You can cancel your subscription at any time.

Get access
130
courses
1000
exercises
2000+
hours of theory
3200
tests

Sign up

Programming courses for beginners and experienced developers. Start training for free

  • 130 courses, 2000+ hours of theory
  • 1000 practical tasks in a browser
  • 360 000 students
By sending this form, you agree to our Personal Policy and Service Conditions

Our graduates work in companies:

Bookmate
Health Samurai
Dualboot
ABBYY
Suggested learning programs
profession
Development of front-end components for web applications
10 months
from scratch
Start at any time

Use Hexlet to the fullest extent!

  • Ask questions about the lesson
  • Test your knowledge in quizzes
  • Practice in your browser
  • Track your progress

Sign up or sign in

By sending this form, you agree to our Personal Policy and Service Conditions
Toto Image

Ask questions if you want to discuss a theory or an exercise. Hexlet Support Team and experienced community members can help find answers and solve a problem.