Иерархия наследования и дизайн - избегая множественного наследования

Я работаю над 3D-игрой и нуждаюсь в советах о том, как лучше всего разрабатывать и структурировать свой код, чтобы добиться того, что я собираюсь, без использования плохих методов, таких как множественное наследование.

В основном я все время стараюсь реализовать множественное наследование с помощью простых интерфейсов.

Например, у меня есть абстрактный базовый класс, Physical_Object, и у меня есть абстрактный класс, полученный из него, Controllable, и у меня есть класс, полученный из Controllable, Drone ,

Controllable должен реализовать метод обновления, который, в зависимости от состояния управляемого, будет либо вызывать метод обновления AI, либо метод обновления, основанный на состоянии клавиатуры /контроллера.

У Drone есть разные сегменты, из которых взаимозаменяемы и имеют разные способности.

Некоторые из этих сегментов, а также некоторые другие будущие игровые объекты должны иметь возможность нацеливать /отслеживать луч от их источника до места, где они нацелены. Поэтому я решил создать новый абстрактный класс /интерфейс, который требует реализации target.

В настоящее время у меня есть абстрактный класс Drone_Segment, который позволяет мне полиморфно управлять взаимозаменяемыми сегментами Drones. И каждый из них имеет иерархии, например, Drone_Turret_Segment: Physical_Object-->Controllable-->Drone_Segment->Drone_Turret_Segment.

В сущности, учитывая текущую структуру и дизайн, самый быстрый и простой способ добавить метод target ко всем классам, которые ему потребуется, без множественного наследования, добавить и внедрить target в Controllable. Но это будет иметь недостаток, что объекты, которые не имеют логического использования для метода, наследуют его.

Другим вариантом является создание простого интерфейса и создание только объектов, для которых целевой метод наследуется от него, но я не могу понять, как лучше всего это сделать без множественного наследования, то есть: Physical_Object-->Controllable-->(Drone_Segment,Targeting_Object)->Drone_Turret_Segment.

Каковы некоторые способы сделать это?

5 голосов | спросил MVTC 6 AM00000070000003331 2013, 07:43:33

4 ответа


9

Обратите внимание, что нет ничего плохого в множественном наследовании. Проблема наследования алмазов - это ... проблема. Обычное множественное наследование без общих оснований весьма полезно.

Тем не менее, наследование вообще - это, как правило, неправильный подход, если вы не используете функциональные интерфейсы. Многие иерархии классов, в том числе и ваши собственные, в конечном итоге выглядят слишком похожими на таксономию реального мира.

Рассмотрим агрегацию /состав по наследованию. Вместо того, чтобы думать «a Drone is-a Controllable в поведении «подумайте об этом» a Drone имеет Controllable.

Вы можете создавать статическую агрегацию или динамическую композицию. Последнее имеет много преимуществ, но первое довольно хорошо.

Обычная статья для ссылки с более подробным объяснением - Развивайте свою иерархию .

ответил Sean Middleditch 6 AM00000090000001131 2013, 09:32:11
3

Injection Dependency может решить эту проблему.

Объект верхнего уровня, а не реализация или переопределение определенного процесса, определяет, что для него требуется объект, способный его выполнить. Он также определяет , что этот объект должен делать, т. Е. Он определяет интерфейс компонента. Тогда меньшие, простые и независимо реализованные объекты должны выполнять этот интерфейс. Это назад от классического полиморфизма, где объекты низкого уровня определяют и реализуются объекты высокого уровня, поэтому имя Dependency Принцип инверсии .

Например, вашему Drones может потребоваться объект, который реализует Update() и выполнить их обновление через это свойство. Этот объект не зависит от цепочки наследования. Объект, заполняющий интерфейс, может работать с помощью процесса AI, или он может отображать входные данные проигрывателя, или он может следовать сценарию и т. Д. Нет дублирования кода, потому что каждая реализация именно то, что ему нужно, и не более, но также и ненужное наследование в дочернем классы. Нет множественного наследования.

Обратите внимание, что цели этой архитектуры примерно такие же, как и все популярные на этом сайте Архитектура компонента-объекта . Идея состоит в том, чтобы удалить функциональные части из определений объектов, сделать функции модульными и улучшить хрупкие программы, созданные с использованием наследования напрямую.

ответил Seth Battin 6 AM00000080000000431 2013, 08:40:04
1

Мне действительно кажется, что вы хотите использовать множественное наследование, чтобы смешивать разные карманы функциональности, чтобы сформировать что-то новое. Хотя инъекция зависимостей может быть полезна в иерархии наследования, лучшим вариантом будет формирование совокупных композиций объектов.

Использование архитектуры на основе компонентов - простой и естественный способ объединить разные типы игровых объектов. То, что вы на самом деле делаете на фундаментальном уровне, создает новые вещи из ранее существовавших реализаций. Это то, на чем основана архитектура на основе компонентов: вы создаете объекты, основанные на том, что они делают, вместо использования иерархий наследования, которые организуют реализацию и код, основанный на абстрактных идентификаторах имен.

Архитектура на основе компонентов позволит вам избежать возрастной проблемы функций, ползущих вашу иерархию наследования, чтобы избежать дублирования кода.

ответил RandyGaul 6 AM00000090000002031 2013, 09:35:20
1

Я бы рассмотрел конструкцию компонентов

http://gameprogrammingpatterns.com/component.html http://www.gamasutra.com/blogs/MeganFox/20101208/88590 /Game_Engines_101_The_EntityComponent_Model.php

Он использует классы-оболочки и загружает их с помощью повторно используемых компонентов. Это имеет ряд преимуществ. Во-первых, «сглаживает» дерево наследования. Скажем, у вас есть суперкласс с двумя подклассами: шинами и ступеньками. Танки - это подкласса Тред. Но что, если вы хотите бак с шинами? Вы унаследовали от танков, чтобы повторно использовать логику пистолета, или вы наследуете шины, чтобы получить колесную логику. Или вы наследуете от обоих и получаете страшный бриллиант? . При разработке компонентов вы можете иметь общий класс транспортного средства, а затем компоненты. Двигателем может быть один тип компонентов (подрезанный в шины, колеса, пропеллеры или крылья), а пушка может быть другим типом компонента. По сути, системы компонентов полезны, если у вас есть широкий массив объектов, которые повторно используют функциональные возможности, но не обязательно наследуют друг от друга.

Есть и другие преимущества. Подобно тому, как вы можете хранить все однотипные компоненты рядом друг с другом в памяти и одновременно обновлять один тип компонента. Тогда вы потратите меньше времени на случайные компоненты, но только беспокоитесь об этом, если вам нужно повысить производительность.

ответил mobo 6 PM00000040000000931 2013, 16:05:09

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132