我跟随MOOC,在其中我有以下代码。首先,有两种类型:
class EasyMonster
{
//stuff
}
和
class DifficultMonster : EasyMonster
{
//same stuff, just overrode some functions
}
在主程序中,功能如下:
private static EasyMonster MakingMonster()
{
if stuff
{
return new EasyMonster();
}
else
{
return new DifficultMonster();
}
}
我对C#理论的理解是,这个函数的结果应该被视为一个EasyMonster
- 类型的对象,程序应该没有办法记住,有时候结果是函数MakingMonster()
在开始时是DifficultMonster
- 类型。
然而,在其余的代码中,我发现了这个:
EasyMonster monster = MakingMonster();
// Blah Blah
if (monster is DifficultMonster)
accDiff++;
else
accEasy++;
有人可以解释一下吗?
编辑:我不明白为什么行EasyMonster
的{{1}}部分不会强制返回的变量类型private static EasyMonster MakingMonster()
。为什么合法?
答案 0 :(得分:1)
如果一个类继承自基类,则可以始终定义一个具有签名(提醒,即方法头)的方法,该方法返回基类类型的对象。
由于派生类继承了基类中的所有组件,因此它也可以有效地被视为基类。运行时总是会找到一个具有兼容属性,方法等的对象。
所以编译方式它完全没问题,并且永远不会破坏返回基类的实例,即使你在实现中提供派生类。
我对C#理论的理解是这个函数的结果 应该被视为一个EasyMonster类型的对象,应该有 没有办法让程序记住有时候的结果 函数MakingMonster()在开头就是 DifficultMonster型。
所以这不完全正确。语法说,这里返回的任何对象都将符合EasyMonster
- 对象的定义。它本身不需要是EasyMonster
,只有继承树中的某个地方实际上是类EasyMonster
。但是返回的对象确实保留了它构造的所有信息。 (因为它是一个引用类型,所以你只能获得对象的引用。所以它指的是DifficultMonster
)的实例。
我不明白为什么EasyMonster系列的部分原因 私有静态EasyMonster MakingMonster()并没有强制类型 变量返回EasyMonster。为什么合法?
将对象返回或转换为基类型并不会剥夺"多余的"在继承期间添加的部分。它只是表示该对象现在应该被视为运行时的基本类型。
这也意味着,你必须要小心重写那些并非首先被覆盖的东西。您始终可以使用new
关键字覆盖事物(方法,属性,事件等),但如果您不知道覆盖是如何工作的,则会产生意外结果。有关详细信息,请查看here或here。
is
关键字只检查您的引用所指向的对象是否与运行时的类型描述兼容,请参阅here。如果您使用类提供的继承树,则DifficultMonster
同时为EasyMonster
和 DifficultMonster
。
如果你想通过你的类结构派生你的类确实不一样,那么你必须引入一个基类型,两个类都继承了这个类,比如说Monster
:
class Monster
{
// implement all that monsters have in common.
}
然后您从基类EasyMonster
DifficultMonster
和Monster
class EasyMonster : Monster
{
// implement specific things for the easy monster.
}
class DifficultMonster : Monster
{
// implement specific things for the difficult monster.
}
然后该方法将返回类型为Monster
的对象:
private static Monster MakingMonster()
{
if stuff
{
return new EasyMonster();
}
else
{
return new DifficultMonster();
}
}
现在检查只有在DifficultMonster
而不是EasyMonster
的情况下才会生效。
Monster monster = MakingMonster();
// Blah Blah
if (monster is DifficultMonster)
accDiff++; // only counts if the object is DifficultMonster
else
accEasy++; // only counts if the object is not a DifficultMonster
因为你可能不希望任何人创建你的基类的实例,因为它没有任何意义让一个未定义的怪物坐在那里,你可以设计Monster
类是抽象的。然后只能实例化派生类。
abstract class Monster { }
private static Monster MakingMonster()
{
return new EasyMonster(); // still works.
}
private static Monster MakingMonster()
{
return new Monster(); // will create compiler error.
}
答案 1 :(得分:0)
好的,我找到了答案的元素:
似乎是:1)
private static EasyMonster MakingMonster()
{
if stuff
{
return new EasyMonster();
}
else
{
return new DifficultMonster();
}
}
相当于:
private static EasyMonster MakingMonster()
{
if stuff
{
return ((EasyMonster)new EasyMonster());
}
else
{
return ((EasyMonster)new DifficultMonster());
}
}
并且使用“stuff”返回(EasyMonster)stuff
DifficultMonster
- 类型对象返回类似于“a DifficultMonster
- 类型对象的内容,用于在EasyMonster类型中投放的时刻,但仍然可以转换为他原来的类型“
来源(法语,抱歉小伙伴< 3):https://openclassrooms.com/courses/programmez-en-oriente-objet-avec-c/la-poo-et-le-c-1 §:“La conversion entre les objets avec le casting”