πŸ“œ ⬆️ ⬇️

Goodbye object-oriented programming



I have been programming in object-oriented languages ​​for decades. The first of these was C ++, then Smalltalk, and finally .NET and Java. I fanatically took advantage of the inheritance, encapsulation, and polymorphism of these three pillars of the object-oriented programming paradigm. I really wanted to take advantage of the promised reuse and touch the wisdom accumulated by my predecessors in this new and exciting field. I was worried about the very idea that I could store the objects of the real world into classes and thought that the whole world could be carefully arranged in places.

I could not be wrong more.

Inheritance - The First Fallen Pillar



')
At first glance, inheritance is the main advantage of the OO paradigm. All the simplified examples of hierarchies cited to us seemed to make sense.



And "reuse" is generally the term of the day. No, perhaps even a year, or even more. I swallowed it all up and ran to implement my new-found vision in real projects.

The problem of bananas, monkeys and jungle


With faith in my heart and problems waiting for a decision, I began to create class hierarchies and write code. And the world was in harmony. I will never forget that day when I was going to get all the benefits of reuse by inheriting an existing class. I have been waiting for this moment for a long time.

There was a new project, I did not forget about my idea with the class and was very enthusiastic. No problem. Reuse hurries to the rescue. You just need to take a class from another project and apply it. Well ... actually ... not just a class. You need a parent class. But ... But that's all. GHM ... wait ... it seems that we need another parent of a parent ... And then ... well, we need ALL parents. Good ... good ... I'll deal with it. No problem.

Well, great. Now it is not compiled. Why??? Oh, I see ... This object contains this other object. So I need him too. No problem. Wait ... I don't need just that object. I need his parent, and parent's parent, etc. For every nested object I need parents, as well as their parents, and their parents, parents ... Yeah. Joe Armstrong, the creator of Erlang, once said beautiful words:

The problem with OO languages ​​is that they pull all of their surroundings behind them. You just wanted a banana, but as a result you get a gorilla holding this banana, and all the jungle in addition.

Solving the problem of banana, monkeys and jungle


You can get out of the situation without creating too deep hierarchies. But since inheritance is the key to reuse, any restrictions imposed on this mechanism will unambiguously reduce the benefits derived from it. Right? Right. So what should a poor object-oriented programmer do when he blindly believed promises? Aggregate (contain) and delegate (delegate). More on this later.

Diamond problem


Sooner or later, this problem will raise its ugly and, depending on the language, insoluble head.



Most OO languages ​​do not support this, although it looks quite sober. So what's up? Let's look at this pseudocode:

Class PoweredDevice {
}

Class Scanner inherits from PoweredDevice {
    function start() {
    }
}

Class Printer inherits from PoweredDevice {
    function start() {
    }
}

Class Copier inherits from Scanner, Printer {
}

, Scanner Printer start. start Copier? , Scanner? Printer? .


: . . - . … ? ! .

Class PoweredDevice {
}

Class Scanner inherits from PoweredDevice {
    function start() {
    }
}

Class Printer inherits from PoweredDevice {
    function start() {
    }
}

Class Copier {
    Scanner scanner
    Printer printer
    function start() {
        printer.start()
    }
}

Copier Printer Scanner. start Printer. Scanner’. β€” .


, . . . … . . , , … , … - … . , , . ??? … ( Java, , ):

import java.util.ArrayList;

public class Array
{
    private ArrayList<Object> a = new ArrayList<Object>();

    public void add(Object element)
    {
        a.add(element);
    }
 
    public void addAll(Object elements[])
    {
        for (int i = 0; i < elements.length; ++i)
            a.add(elements[i]); // this line is going to be changed
    }
}

: . . : add() addAll(). add() , addAll()β€” add(). :

public class ArrayCount extends Array
{
    private int count = 0;
 
    @Override
    public void add(Object element)
    {
        super.add(element);
        ++count;
    }
 
    @Override
    public void addAll(Object elements[])
    {
        super.addAll(elements);
        count += elements.length;
    }
}

ArrayCount β€” Array. , ArrayCount . .


. :

public void addAll(Object elements[])
{
    for (int i = 0; i < elements.length; ++i)
        add(elements[i]); //    
}

, , . . . . ArrayCount addAll() addAll(), add(), . add() , , addAll() . , .

, , . , . ! .


. Β« Β» Β« Β». . , , . .

… . -. . , . , .


, , , . , ? , β€” ? , ? ?

β€œ/” , (), β€” (). , (. ). , - .


… β€œ/” . ?

(Containment).

, . , β€œ/”. . - , . , β€œ/”, . . β€” . , , , ..

β€” . . ? , - , , . , . :


. , . , . , , . , .

,




, β€” - . , . , . β€” . !!! … , …

(The Reference Problem)


, , . , , . , , . ! ? - , , . , .


. , , , , , .. . , . , , , β€” . - . , .

,




β€” - . . , , . , , -. . - . , , . -, .




. - , -. , , . , . . , - .

?


, . . : . , . , . .

Source: https://habr.com/ru/post/307168/


All Articles