Why does everyone hate multiple inheritance in C++ and what’s your difference to mixins?

Asked

Viewed 3,148 times

16

I’ve always heard that multiple inheritance in C++ is chaos. Why? It wouldn’t be technically the same thing as using mixins in languages such as Ruby?

And what is this abstract class of Java? It’s a mixin java?

2 answers

20


Wrong premise

I don’t know why everyone hates multiple inheritance in C++. I don’t even know if that’s true. I know a lot of people who don’t. Even people who point out problems in this resource (which is possible to do in virtually any resource of any language) do not usually hate something that can be useful and quiet to use if the person knows what they are doing. Of course I’m talking about thoughtful people.

The problem of multiple inheritance

State

State is one of the things that cause problem in multiple inheritance, where there may be conflict between two or more members. Imagine you have two members with the same name but trying to meet different needs. This is called diamond problem.

Problema diamante

Of course, the same can happen with methods, but it is easier to live with methods with the same name explicitly indicating which implementation you want to use. For status this is implementation detail, in general it is something private, you cannot select which to use. Of course, it can always be solved privately. But there is no guarantee that this will be done. And when you do, you end up complicating enough for the inheritance to stop being advantageous. That’s why I said you can use it, as long as you know exactly what you’re doing.

Builder

There is another problem that the state causes. It is common for it to require a builder. There may be confusion in the calling of these builders. In what order should they be called? What if in the subclass there is a need for interdependence between these states?

It has solution, it is not simple, it is not perfect but it can be solved. It has to know how to solve.

The problem is aggravated by the existence of overload of methods (different signatures).

Demeanor

The diamond problem also occurs in conventional methods but is easier to solve.

Mixin

The exact conceptualization depends on who is speaking. There is no clear definition, it varies from language to language.

It is usually considered a class that cannot be instantiated directly, has no state and neither builders (nor would it make sense by previous characteristics).

It is possible to add some form of state through fields that are nothing more than state access methods.

It is used to add behavior to a class not to be a complete class in every sense.

This greatly simplifies inheritance. Avoids the above problems. It usually solves well what the programmer needs.

It’s easier to implement mixin in dynamic languages since one of its characteristics is to resolve these possible conflicts at runtime.

Not everything is perfect

Contrary to what you try to sell mixin He’s not trouble-free. It can break encapsulation in certain languages such as Ruby and its more dynamic feature prevents certain checks at compile time. In addition, conflict resolution is usually done by automatic scope rules and the compiler can make bad choices.

Other solutions

Several languages have adopted alternative ways to meet the need for multiple behaviors without incurring the above problems.

Interfaces

Adopted by Java and C#, for example. Interface cannot be instantiated, has no state or constructors.

It is a good solution, but it also fails to have implementation in the methods. This requires writing extra code or resorting to utility classes to get code reuse. A modernization even allows having but does not change the main about the state.

One abstract class is not an interface because it has been, so constructor also and methods can be implemented.

Traits

Roughly speaking it’s basically the mixin without the possibility of camps.

Preferred in static languages because it is easy to solve everything at compile time.

Usually there is some explicit way in the language to resolve conflicts. It takes a little more work but the results are usually more appropriate.

Extension method

It is a way to add extra implementation to a class. It does not actually add a method to the class but creates an illusion only. It does not have access to the internal state (private) of the class). I have only seen it implemented in C# and in a certain way in D. It is more syntactic than semantic.

The combination of interfaces with extension methods can be considered a limited form of trait. If there were Extension properties (which are equivalent to Ruby’s "attributes") would match mixin.

Default method

Implemented in Java 8 to give better reuse of code. It is basically an interface with implementation in the method.

It’s a lot like a trait. I wouldn’t even know what the real difference is except for the fact that it’s common, but not mandatory, that the language gives some specific support and syntactically indicates that that interface has a different semantics.

And it might even look like mixin with the use of methods getters and setters. It’s not the same because it doesn’t deal with the state directly. And to tell you the truth as I still do not know this new functionality, I do not know all limitations to do this.

That’s the closest thing to mixin that Java (8) arrives.

Other

Less popular languages have found other ways to solve multiple inheritance problems. In link about the diamond problem has some descriptions.

Completion

Note that none of these alternative forms, despite being considered ways of obtaining multiple inheritance, are to multiple inheritance as defined.

Inheritance abuse

Inheritance is used in exaggeration. Multiple inheritance even more. It is not so necessary. Think about it, to use inheritance we must ask if the daughter class is the mother class ("a car is a vehicle"). It is rare for a class to be two things at the same time. In general it is one thing and has certain extra features.

There is a lot of storm over this. The biggest issue there is that you rarely need multiple inheritance. And staying in the same kind of analogy, people look at the glass half empty when they should look half full. You can do more with this feature available. Doing more is good when you know how to program.

How to use multiple inheritance well in C++

C++ could have a better solution for multiple inheritance, it could be easier. But when it was created no one understood the full implications of what it was creating.

Anyway this is a very powerful feature. Have to be careful but you can do very strong things with it.

It is true that C++ does not make it easy but it is possible to use the same interface techniques, mixins and traits. Just the programmer does this. It’s his choice. He just has the choice not to follow this form. And if he needs a complete class inheritance he can do too, in other languages he can’t. It is part of the philosophy of language to allow the programmer to choose what is best for him. It is not part of the philosophy of language to limit the programmer’s ability.

If you want to use mixin in C++, do this. The language is powerful enough to do this way. The compiler just can’t guarantee that this technique has been adopted correctly (not that other languages get much better). It needs a little more discipline but it’s possible and it’s not even extra work.

Compiler implementation

Of course it is difficult to implement a compiler to handle this, it is more difficult for the programmer to learn how to use it and needs to be more careful when using this feature. C++ compiler implementers must claim more than users.

Extra resources

  • Excellent answer, it went much further than the question asked. I didn’t know there were so many ways to reuse code in classes! Obs.: Only left to put the title "class abastrata" there between interfaces and traints. =)

  • It is that abstract class is a common class except that it cannot be instantiated since some methods may not have implementation. That is, it does not help at all the focus of the question that is multiple inheritance. You can still only have an inherited class in these languages, whether abstract or concrete.

  • 1

    I deserve the acceptance but not the vote? in the reply? You know you can vote as well as accept? You can vote for anything from website that you find useful. Look at the [tour]. I saw that you never voted for anything. Don’t miss this opportunity, help the community sort the content and still win medals for it.

  • "Wrong premise", I fully agree with this, in fact, people (I include myself in this) have the tendency and convenience to complain, to defect and/ or hate what they do not understand, do not know what it is for or can not use. I hated OO until I learned, I hated code with Doctrine, until I learned, I even hated this business called Composer(best home invention after the internet).

6

One of the problems of multiple inheritance is to determine the origin of methods in the specialized class.

For example, consider the following classes:

Class A
{
  public:
  int a;
  int b;
  private:
  void metodo(){}
}

Class B
{
  public:
  int c;
  int d;
  private:
  void metodo(){}
}

Class C: public A, public B
{
}

Where does the method that class C inherits from A and B come from? Which one?

Abstract classes of Java function like the virtual classes (I believe that is the term) of C++, you cannot instantiate an object of these classes and concrete classes that inherit from the abstract are required to implement the methods inherited from the abstract class.

An example:

public abstract class A {
  boolean eImpar(int num) {
    //Codigo
  }

  boolean abstract ePar(int num); 
  //Nem todos os métodos em classes abstratas     
  //precisam ser abstratos, mas quando forem
  //NÂO devem ter implementação.
}

public class B extends A {
  boolean ePar(int num) {
    //Essa função PRECISA ser implementada na classe.
  }
}

public class Main {
  public static void main(String[] args) {
    A exemplo1 = new A(); //Erro! Classe abstrata não pode ser instanciada!
    A exemplo2 = new B(); //Possivel!
  }
}

Another concept similar to abstract classes in Java is that of interfaces, and it is through them that you implement the "multiple inheritance" of Java.

Example:

public class A {}
public class B {}
public class C extends A, B {} //Errado!

public interface I {
  public int getNum();
}
public class A {}
public class B extends A implements I {
  public int getNum() {
    //Tem de implementar o metodo da interface!
  }
}

I hope it helped.

  • 1

    Metodos em classes abstratas não precisam estar definidos, e a palavra-chave 'abstract' é opcional. is giving too much room for misinterpretation, how about: Nem todos os métodos em classes abstratas precisam ser abstratos, mas quando forem não devem ter implementação ? Otherwise your answer is right, deserves a +1.

  • I’m not sure if I got it wrong again or you’re mixing the concepts. To make an abstract method in an abstract class you must keyword abstract. In interfaces the story is another, although you do not use modifiers in your method it is implicitly public abstract. Agrees?

  • I mixed the concepts myself, I made an abstract class here just for fun in a project, I saw that I needed the abstract even.

  • 1

    No problem. I think you were confusing it with interface. The important thing is that you fixed the answer.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.