从C#中的继承类转换数据类型

Sir*_*Sir -1 c# inheritance unity-game-engine

我试图理解我的团结项目的继承,但似乎已经找到了我的设置的限制.在写作的过程中,我感到很困惑,因为我仍在学习正确理解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<Node> n,Vector3 p){}
    virtual public void Exit(List<Node> n, Node curNode){}
}
Run Code Online (Sandbox Code Playgroud)

现在这个工作正常,直到我必须访问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();
Run Code Online (Sandbox Code Playgroud)

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

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

Eri*_*ert 5

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

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

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

  • "是"检查是运行时类型检查; 不要对多态行为进行运行时类型检查; 使用虚拟方法.

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

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 */
}
Run Code Online (Sandbox Code Playgroud)

好的,现在我们想要执行处理程序......

 MyBehaviour b = whatever;
 b.Handler.Enter();
Run Code Online (Sandbox Code Playgroud)

完成.不需要临时变量.没有运行时类型检查.没有"如果".行为提供了一种服务; 你使用这项服务.您不必为了使用它提供的服务而询问行为类型; 如果你这样做,在设计层面可能出现问题.


Fat*_*tie 5

有一点需要考虑.说你有导弹,手榴弹,子弹.看起来你正试图让它们来自抛射物.

"算了吧!"

作为一个gedanken实验,写一些(比如20)"迷你行为".(这些可能包括"飞直","飞得相当直","飞入抛物线""摇摆上下""悸动""悸动""爆炸时爆炸""爆炸时爆炸""造成飞溅损坏""忽略敌人""不要忽视敌人""随机爆炸""随机爆炸是用户在GameCenter"等等等等等)).

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

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

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

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

 [ actual thing ]  your bullet model
Run Code Online (Sandbox Code Playgroud)

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

 [ actual thing ]  your bullet
Run Code Online (Sandbox Code Playgroud)

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

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

然后,那就是你的"子弹".

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