Преобразование типа данных из унаследованных classов в C #

Я пытаюсь понять наследование для моего проекта единства, но, похоже, нашел ограничение для моей установки. Я сам смутился, когда писал это, потому что я все еще учился правильно понимать C #.

У меня есть набор classов, которые наследуют, и они разбиваются на два разных поведения таким образом, что у меня есть правильная ссылка.

Затем мне нужно отбросить их, чтобы я мог получить доступ к методу в одном из этих classов. Поэтому моя структура выглядит так:

public class Behaviour : Position { public Handler reference; public Behaviour(int tx, int ty, Handler refer) : base (tx,ty){ reference = refer; } // overload public Behaviour(int tx, int ty) : base (tx,ty){} } public class Behaviour2 : Position { public SettingsHandler reference; public Behaviour2(int tx, int ty, SettingsHandler refer) : base (tx,ty) { reference = refer; } } public class SettingsHandler : Handler { public Settings level {get;set;} } public class Handler : MonoBehaviour{ virtual public void Enter(List n,Vector3 p){} virtual public void Exit(List n, Node curNode){} } 

Теперь это работало нормально, пока я не получил доступ к Handler.Enter или Handle.Exit. Тогда я заблудился о том, как правильно установить тип.

Поэтому я делал что-то вроде этого:

 //need to set temp : ??? temp; if(path[i] is Behaviour2){ temp = (Behaviour2)path[i]; } else { temp = (Behaviour)path[i]; } temp.reference.Enter(); 

Какой должен быть тип temp здесь?

Я думаю, что, возможно, неправильно понял наследование, поскольку я, похоже, получаю проблемы с типом. У C # есть решение для этого – я не могу быть единственным, кто застрял. Но мой мозг запутывается, пытаясь следовать за всем этим.

Ваша проблема связана с тем, что базовые classы плохо разработаны, в первую очередь, следующими способами:

  • Иерархия не имеет смысла. Поведение – это не особый вид позиции. Предпочитают композицию для наследования.

  • Поля никогда не должны быть общедоступными. Используйте свойства, а не поля .

  • «is» проверяет проверки типа времени выполнения; не выполняйте проверки типа времени выполнения для полиморфного поведения; используйте виртуальные методы.

Давайте перепроектируем вашу иерархию.

 abstract class MyBehaviour { public Position Position { get; private set; } public Handler Handler { get; private set; } protected MyBehaviour(int x, int y, Handler handler) { this.Position = new Position(x, y); this.Handler = handler; } } class Behaviour1 : MyBehaviour { /* Whatever */ } class Behaviour2 : MyBehaviour { /* Whatever */ } 

Хорошо, и теперь, когда мы хотим выполнить обработчик …

  MyBehaviour b = whatever; b.Handler.Enter(); 

Готово. Никакой временной переменной не требуется. Нет проверки типа времени выполнения. Нет «если». Поведение предоставляет услугу; вы используете услугу. Вы не должны спрашивать поведение своего типа, чтобы использовать предоставляемую им услугу; если вы это сделаете, вероятно, что-то не так на уровне дизайна.

Одно дело. Скажите, что у вас есть ракета, граната, пуля. Похоже, вы пытаетесь заставить их проистекать из снаряд.

“Забудь это!”

В качестве эксперимента gedanken напишите несколько (например, 20) «мини-поведения». (Они могут включать в себя «летать прямо», «летать прямолинейно», «летать в параболе», «дрожать вверх и вниз», «пульсировать», «сильно бить», «взрываться при ударе», «взрываться при низком уровне», наносить ущерб от всплеска » игнорировать врагов “” не игнорировать врагов “” случайным образом взрываются “,” случайным взрывом является пользователь на GameCenter “и т. д. и т. д. и т. д. и т. д. и т. д.).

Теперь где-то у вас будет модель вашей «гранаты». (Будь то compilation, или для пула – или что-то еще.) Просто вставьте все мини-поведения, которые вы хотите. Это как .. фотошоп, понимаешь? Ваша концепция «снаряд» не имеет никакого смысла – кому это нужно? Я имею в виду, что это GameObject.

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

Еще один способ взглянуть на то, что я говорю: в вашей системе выше вы думаете о том, чтобы в каждом из этих сценариев было более одного поведения, не так ли? Таким образом, ваш сценарий «bullet» (полученный из вашего скрипта master-replacement-for-GameObject «снаряд») на самом деле сделает пулю для всех вещей, которые делает пуля, я прав ? (это заставит его летать, взорваться, поразить вещи, иметь очки, вращаться .. бла-бла). Ну, я могу остановить вас прямо там – никогда не бывает поведения, чем одно. Ты видишь? Все эти «маленькие поведенческие» творения, которые вы пишете, являются их собственными вещами, и все они должны быть их собственным компонентом (точно так же, как и Unity уже дает вам – весну, коллайдер, что угодно).

Еще один способ взглянуть на это: не забывайте, что Unity как система ECS – это реальные вещи . Где-то у вас на самом деле будет «пуля».

  [ actual thing ] your bullet model 

Таким образом, это будет GameObject, и либо compilation, либо просто сидящий на сцене в иерархии в какой-то позиции. (В игре вы клонируете его и используете.) Там мало смысла называть его «моделью» (что еще это может быть, это просто … пуля)

  [ actual thing ] your bullet 

Он будет иметь свойство .name (очень вероятно … «пуля» или «модель пули» или что-то еще), положение, средство визуализации и т. Д. И т. Д.

Хорошо начинать назад в программном обеспечении, чтобы понять, что бессмысленно / ортогонально концептуально – у вас «должно быть» то, что я только что описал, так что же это class «пуля»? Что оно делает? Вам нужно / должно / иметь вещь, которую я только что описал («пуля»), но вам совсем не нужен class «пуля», поэтому забудьте об этом. Просто получите GameObject, и со временем (возможно, с вашими дизайнерами и т. Д.) Вставьте все необходимое на нем (аудио, десяток небольших поведений, вещи Unity дают вам, как RigidBody и т. Д.).

Тогда это ваша «пуля».

Поэтому интересно подумать об этом.

  • Почему структуры не поддерживают наследование?
  • Наследуются ли виртуальные деструкторы?
  • не могут вызвать защищенные функции базового classа?
  • Нельзя наследовать от std :: vector
  • Когда использовать собственное наследование C ++ над составом?
  • Почему мы назначаем родительскую ссылку на дочерний объект в Java?
  • Переопределение переменных экземпляра суперclassа
  • Java: если A расширяет B и B расширяет Object, то это множественное наследование
  • Наследование backbone.js
  • Поиск имен в шаблонах C ++
  • Класс не является абстрактным и не отменяет абстрактного метода
  • Interesting Posts

    Laravel 5 – глобальная переменная вида Blade, доступная во всех шаблонах

    Материнская плата с низким энергопотреблением для домашнего сервера Windows

    Что рекомендуется для нереста streamов из сервлета в Tomcat

    Получите Windows 7, чтобы запомнить мою конфигурацию с несколькими мониторами и автоматически восстановить окна при повторном подключении

    Показать и скрыть вид с помощью анимации слайдов вверх / вниз

    Как читать указанную строку в текстовом файле?

    Как изменить цвет и шрифт в ListView

    Не удалось импортировать проект Eclipse в Android Studio

    Как распознать, содержит ли строка символы unicode?

    NSMutableURLRequest не подчиняется моему тайм-аутуInterval

    Android, ListView IllegalStateException: «Содержимое адаптера изменилось, но ListView не получил уведомление»

    jQuery ajax (jsonp) игнорирует тайм-аут и не запускает событие ошибки

    Почему для x86 (-64) для подписчиков и без знака умножаются разные инструкции?

    Концепция многопоточности Java и метод join ()

    HTML5 Video не работает с тегом AngularJS ng-src

    Давайте будем гением компьютера.