【问题标题】:call childrens method from parent从父级调用子级方法
【发布时间】:2015-07-28 09:20:41
【问题描述】:

我有一个名为 MyGameObjectsList<GameObject>
我有一个名为DrawableGameObject 的类,它继承自GameObject。在我的列表中不仅有GameObjects,还有DrawableGameObjects。
DrawableGameObject 有一个名为 Animation 的属性,而 GameObject 没有。
我想做以下事情:

for (int i = 0; i < MyGameObjects.Count; ++i) {
    if (MyGameObjects[i].GetType() == typeof(DrawableGameObject)) {
        // use Animation property of MyGameObjects[i] here...
    }
}

但它不会让我。 如果有办法做到这一点,请帮助我^^

【问题讨论】:

  • 为什么不重构你的代码,让所有对象可以都有动画,但只有其中一些有动画,然后你可以使用基类编写代码,就好像动画将是可用,但它不会为任何东西设置动画。您应该研究 Liskovs 替换原则,这是 SOLID 原则的一部分。
  • 想想虚拟方法。

标签: c# list oop inheritance types


【解决方案1】:

您可以强制转换对象并访问其成员。像这样的:

foreach (var gameObject in gameObjects)
    if (gameObject is DrawableGameObject)
        (gameObject as DrawableGameObject).Animation();

或者,更接近于你的做法:

for (int i = 0; i < gameObjects.Count; i++)
    if (gameObjects[i].GetType() == typeof(DrawableGameObject))
        ((DrawableGameObject)gameObjects[i]).Animation();

您还可以通过仅确定一次强制转换然后执行更快的空值检查来稍微优化这一点:

foreach (var gameObject in gameObjects)
{
    var obj = gameObject as DrawableGameObject;
    if (obj != null)
        obj.Animation();
}

但是请注意,这是对Liskov Substitution 的明显违反。您的代码显然在错误的抽象上运行。问题中没有足够的信息来就此事提出具体建议,但如果您需要以这种方式强制转换,则您的类型设计不正确。

【讨论】:

  • if (gameObject is DrawableGameObject) (gameObject as DrawableGameObject).Animation();效率不如: var obj = gameObject as DrawableGameObject); if (obj != null) obj.Animation();
  • @rbaghbanli:是的,但我非常怀疑微优化在这里真的是一个问题。不过,值得注意的是。
  • 我考虑过将Animation 属性也添加到GameObject 类中,以便在检查类型后能够使用它,但这会导致DrawableGameObject 完全为空和GameObject 是一团糟。
  • @NylonFreak:好吧,说句公道话,考虑到您在这里要完成的工作,代码已经有点乱了。我建议将您的对象/继承模型带到codereview.stackexchange.com,以获取有关更清洁的面向对象方法的一些建议。
  • @David 查看关于 rbaghbanlis 答案的评论。你怎么看?
【解决方案2】:

只需将其转换为 DrawableGameObject:

for( int i = 0; i < MyGameObjects.Count; i++ )
    if( MyGameObjects[i] is DrawableGameObject )
    {
        var drawable = (DrawableGameObject)MyGameObjects[i];
        ...
    }

或者,更高效一点:

for( int i = 0; i < MyGameObjects.Count; i++ )
{
    var drawable = MyGameObjects[i] as DrawableGameObject;
    if( drawable != null )
        ...
}

如果转换无效,as 运算符将返回 null。

【讨论】:

    【解决方案3】:

    你必须投射它。

    for (int i = 0; i < MyGameObjects.Count; ++i) {
        if (MyGameObjects[i].GetType() == typeof(DrawableGameObject)) {
            ((DrawableGameObject)MyGameObjects[i]).Animation;
        }
    }
    

    【讨论】:

    • 非常感谢...我打算将 Animation 属性添加到 GameObject 并且仅在我检查类型时使用它。那会以一团糟而告终...我曾尝试投射对象,但我像(DrawableGameObject)myGameObjects[i].Animation一样做到了。
    • 多年前,这也是一个微妙的差异让我感到困惑。当您考虑它时,(DrawableGameObject)myGameObjects[i].Animation 实际上是在尝试将Animation 的返回值转换为DrawableGameObject
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-01
    • 2021-05-17
    • 1970-01-01
    • 1970-01-01
    • 2021-04-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多