Так ли уж плохо множественное наследование в данном конкретном сценарии? - PullRequest
2 голосов
/ 17 июня 2020

Сейчас пытаюсь понять «злобу» МИ. Я только что посмотрел видео на YouTube, где парень из js выступает против наследования. Вот его пример (я переписал его на C ++):

struct Robot
{ void drive(); };

struct MurderRobot : public Robot
{ void kill(); };

struct CleanerRobot : public Robot
{ void clean(); };

struct Animal
{ void poop(); };

struct Dog : public Animal
{ void bark(); };

struct Cat : public Animal
{ void meow(); };

Затем он предложил новый класс MurderRobotDog, который, с его точки зрения, не может быть выполнен изящно с помощью наследство. Конечно, с помощью одинарного наследования это невозможно. Но я не вижу никаких проблем в том, чтобы сделать это с MI.

Я думаю, мы могли бы создать базовый класс BarkingObject, в котором был бы весь лай. Затем Собака наследует от Животного, у которого есть общий p oop (), и от BarkingObject. А когда вам нужна собака-робот-убийца, она должна унаследовать от BarkingObject и MurderRobot. В этом больше смысла. MurderRobotDog не может наследовать от живого существа, потому что тогда оно становится живым, а это противоречит определению робота. Конечно, для этого нужно использовать множественное наследование, которое многие люди считают ЗЛОМ. К сожалению, кажется, что мы не можем эффективно повторно использовать различные несвязанные (вам не нужно p oop () для bark (), и случай робота подтверждает это утверждение) без него.

Каковы ваши аргументы против моего предложения?

1 Ответ

1 голос
/ 17 июня 2020

Реализация множественного наследования - это устаревший способ решения подобных проблем.

Состав - новый способ.

Вы определяете интерфейсы , которые описывают конкретное поведение или набор поведений:

struct Murderer
{
    virtual ~Murderer() = default;
    void kill();
};

struct Pooper
{
    virtual ~Pooper() = default;
    void poop();
};

Реальные вещи, такие как кошка, собака или робот, наследуют (т.е. реализуют) эти интерфейсы соответственно. Вы используете dynamic_cast или аналогичный метод времени выполнения, чтобы запросить объект для интерфейса перед тем, как выполнить соответствующее действие.

...