从C#中的inheritance类转换数据类型

我试图理解我的团结项目的inheritance,但似乎已经找到了我的设置的限制。 我在写作时感到困惑,因为我仍在学习正确理解C#。

我有一组inheritance的类,它们基于两种不同的行为进行拆分,这样我就有了正确的引用。

然后我需要转换它们,以便我可以访问其中一个类中的方法。 所以我的结构看起来像这样:

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(); 

临时类型应该设置为什么?

我想我可能误解了inheritance,因为我似乎得到了类型问题。 C#是否有解决方案 – 我不能成为唯一一个陷入困境的人。 但是我的大脑很难搞清楚。

您的问题源于这样一个事实,即基类的设计很糟糕,主要有以下几种方式:

  • 层次结构毫无意义。 行为不是一种特殊的立场。 首选组合inheritance。

  • 字段永远不应该公开。 使用属性,而不是字段

  • “是”检查是运行时类型检查; 不要对多态行为进行运行时类型检查; 使用虚方法。

让我们重新设计你的层次结构。

 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上“等等等等等)。

现在某个地方你会有一个你的“手榴弹”模型。 (无论是预制,还是游泳池等等。) 只需粘贴所需的所有迷你行为即可。 就像.. photoshop,你知道吗? 你的概念“抛射物”有点毫无意义 – 谁在乎呢? 我的意思是它是一个GameObject。

打个比方:假设一家大公司制造了一款名为“Weapony”的游戏引擎,仅用于制作射击游戏。 他们给你一个基本概念“武器”。 真棒。 你过来用它做一个游戏,然后你立即制作自己的“更好”的基础对象.. ArmyWeapon(并开始inheritance它……子弹,手榴弹等)。 那将是……毫无意义,对吧? “武器”就在那里。 只需添加您想要的行为。 那就是现在的情况! 你几乎可以这样说,你只是毫无意义地重命名GameObject。

另一种看待我所说的内容的方法:在上面的系统中,你考虑在每个脚本中放置多个行为,对吧? 因此,你的“子弹”脚本(源自你的“射弹”大师替换为GameObject脚本)实际上会让子弹完成子弹做的所有事情 – 我是对的吗? (它会使它飞起来,炸毁,击中东西,有分数,旋转……等等)。 好吧,我可以阻止你在那里 – 从来没有一个行为不止一件事。 你看? 你写的所有那些“小行为”都是他们自己的东西,他们应该都是他们自己的组件(就像Unity已经给你的那些 – 弹簧,对撞机,等等)。

另一种看待它的方法:不要忘记,Unity作为ECS系统是关于真实的东西 。 在某个地方你实际上会有 “子弹”。

  [ actual thing ] your bullet model 

因此,它将是一个游戏对象,或者是预制或者只是坐在某个位置的层次结构中的场景中。 (在游戏中你将克隆它并使用它。)没有必要将它称为“模型”(它还能做什么?它只是…….子弹)

  [ actual thing ] your bullet 

它将具有.name属性(非常可能……“子弹”或“子弹模型”或其他),位置,渲染器等等。

最好在软件中向后看,看看什么是无意义/正交概念 – 你必须“拥有”我刚刚描述的东西,那么什么是“子弹”类呢? 它有什么作用? 你确实需要/必须/将拥有我刚刚描述的东西(“子弹”),但你根本不需要一个“子弹”类 – 所以忘了它。 只需获得一个GameObject,随着时间的推移(可能与你的设计师等)粘贴你想要的所有东西(音频,十几个小行为,Unity给你的东西像RigidBody等)。

那是你的“子弹”。

所以,考虑这一点很有意思。