Преобразование типа данных из унаследованных classов в C #
Я пытаюсь понять наследование для моего проекта единства, но, похоже, нашел ограничение для моей установки. Я сам смутился, когда писал это, потому что я все еще учился правильно понимать C #.
У меня есть набор classов, которые наследуют, и они разбиваются на два разных поведения таким образом, что у меня есть правильная ссылка.
Затем мне нужно отбросить их, чтобы я мог получить доступ к методу в одном из этих classов. Поэтому моя структура выглядит так:
- В чем разница между переопределением виртуальных функций и скрытием не виртуальных функций?
- когда тег «a» не наследует атрибут цвета родительского тега?
- Являются ли частные члены унаследованы в C #?
- Как я могу инициализировать переменные-члены базового classа в конструкторе производного classа?
- Почему я должен объявлять виртуальный деструктор абстрактного classа на C ++?
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е в подclassе?
- Почему я не могу наследовать статические classы?
- Что такое нарезка объектов?
- Включая другой class в SCSS
- Java / JAXB: Unmarshall Xml для конкретного подclassа на основе атрибута
- Динамическое связывание Java и переопределение метода
- Как виртуальное наследование разрешает двусмысленность «бриллиантов» (множественное наследование)?
- Унаследованы статические переменные
Ваша проблема связана с тем, что базовые 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 и т. Д.).
Тогда это ваша «пуля».
Поэтому интересно подумать об этом.