我正在进行一项多态性的作业,并且已经学习了我在c#中发现多态性的在线教程。我的第一个问题是我正确使用它。我有一个名为gameCreature的父类和两个名为agileCreature和predatorCreature的子类。我在课堂上放入虚拟和覆盖。当我使用循环打印出所有对象时,一切看起来都不错。这是代码
gameCreature[] _creature = new gameCreature[sizeBig];
agileCreature[] _agile = new agileCreature[size];
predatorCreature[] _predator = new predatorCreature[size];
for (int i = 0; i < size; i++)
{
_creature[i] = new gameCreature();
}
for (int i = size; i < sizeMid; i++)
{
_creature[i] = new agileCreature();
}
for (int i = size * 2; i < sizeBig; i++)
{
_creature[i] = new predatorCreature();
}
另外,如果这是正确的。我遇到了另一个问题。我试图调用一个名为consumeCreature的方法,该方法仅在predatorCreature中,但不能调用它。我认为这是因为gameCreature中没有consumeCreature方法。除了向父级添加consumeCreature方法之外,还有另一种方法可以调用consumeCreature方法吗?这是代码。
_creature[_creatureNum].consumeCreature(_creature[ate]);
我可以添加一些内容,因此它知道在predatorCreature中使用consumeCreature。
答案 0 :(得分:1)
如果您确定_creature[_creatureNum]
是predatorCreature
,则可以通过以下方式执行此操作:(_creature[_creatureNum] as predatorCreature).consumeCreature(_creature[ate])
。
请你提供更多背景知识(即,你在哪里得到_creatureNum
,为什么你需要所有生物的数组?)
答案 1 :(得分:1)
在处理多态时,你正在犯一个常见的初学者错误。理想情况下,gameCreature(一组可公开访问的方法)的界面应该只包括所有生物共有的一组动作。因此,您可以使用名为consumeCreature
的抽象方法,而不是使用公共Behave
方法:
// Call this method to make the creature do it's thing
public abstract void Behave();
然后在predatorCreature中覆盖Behave
以调用ConsumeCreature()
(按惯例C#方法以大写btw开头),并且在敏捷生物中可以覆盖Behave
来调用,例如RunAway()
1}}
有意义吗?
答案 2 :(得分:1)
你可以说
((predatorCreature) _creature[_creatureNum]).consumeCreature(_creature[ate]);
当且仅当_creature[_creatureNum]
实际上是predatorCreature
时。如果不是,你会得到一个例外。
您也可以
predatorCreature eater = (_creature[_creatureNum] as preadtorCreature);
if (eater != null) eater.consumeCreature(_creature[ate]);
的优点是它不会导致类强制转换异常。
但是强制转换通常是你没有正确使用多态的标志。一系列东西应该是你用同样方式处理的东西数组,让多态(或者包含行为类型的对象)决定项目之间应该有什么不同。
答案 3 :(得分:1)
首先,看起来您了解多态性的基础知识。 agileCreature
或predatorCreature
中覆盖的方法将被虚拟调用,具体取决于该实例的动态类型。
gameCreature
的任何方法都应适用于所有生物,而不适用于任何一种生物。特定于某个生物的方法应该是那些派生类的方法。
当您只引用基类(predatorCreature
)时,关于在特定子类(例如gameCreature
)上调用方法的第二个问题 - 这是通过 upcasting 。只要类型兼容,就可以完成以下任务:
((agileCreature)(_creature[size + 1])).someAgileMethod();
我会建议不要一味地投射,因为如果这个生物确实不是agileCreature
,将会发生运行时异常。更安全的方法是:
agileCreature c = _creature[size + 1] as agileCreature;
if(c != null)
{
c.someAgileMethod();
}
这将尝试进行强制转换,如果数组索引实际上没有动态类型c
,则null
将为agileCreature
。希望这有帮助!