我有2个类Test(Base)和Program(child)。现在我在向下倾斜时遇到了一些问题。
Test t = new Program();// upcasting-works
Program p = (Program)t;//Downcasting-works
Program q = (Program)new Test();//Downcasting -throws exception.
我想知道为什么抛出异常?可能它是非常基本的,但不知怎的,我没有得到。 是为了那个新对象吗?
感谢。
答案 0 :(得分:7)
这是所有OO系统中的预期行为。简而言之,您无法向下转换为动态类型不匹配的内容。在这一行:
Program q = (Program)new Test();
您正在创建Test
个实例 - 该实例显然与Program
不匹配,因为Test
并非来自Program
。在运行时,计算机检测到这种情况并抛出异常。
另一方面,你有:
Test t = new Program();
在这里,您要创建一个Program
实例 - 实例与Test
匹配,因为Program
派生自Test
。
最后,又乱了,你有:
Program p = (Program)t;
在这种情况下,t
是对Test
的引用,但基础类型实际上是Program
- 在运行时,计算机能够确定是这种情况所以被允许工作。
答案 1 :(得分:6)
每个方格都是矩形,但反之亦然。类似地,派生类的每个实例都是基类的有效实例,但反之亦然。在您的示例中,每个Program
都是Test
,但并非所有Test
都是Program
。
注意:澄清一下,这并不意味着你应该在OOP中从Rectangle继承Square :)这只是一个类比。具有讽刺意味的是,类比是OO设计中众所周知的问题。
答案 2 :(得分:1)
问题是:Test
实例不是 a Program
。它适用于第一种情况,因为实例创建为Program
(在第一行)。
使用强制转换,实际对象的类型(不仅仅是变量)很重要。
答案 3 :(得分:0)
可以这样想,你可以将程序转换为Test,因为Program is A Test。
您无法将Test转换为Program,因为Test不是Program。
当你确定对象是那种类型的时候,向下投射是安全的,只有在安全的情况下才能安全投射。
需要升级通常是一种代码气味,如果你发现你经常需要翻转你的物体,你的设计可能有问题。
希望这有帮助,
编辑:向下传播总是安全吗?
根据我的定义 - 根据我的定义 - 你知道对象的类型,并且你把它放在它的继承树下面。例如 Cat和Dog都继承自Animal,Oak和Birch都继承自Tree。
这样做总是安全的
public void DoThingWithCat(Cat snuggles)
{
snuggles.Meow();
DoThingWithAnimal(snuggles); // this is always OK, because we know
// the type of snuggles, and we know
// snuggles is an animal
}
这是一个UpCast。这样做是不安全的,这也就是代码是代码味道,如果你需要这样做,你的对象层次结构可能有问题。
public void DoSomethingElse(Animal anAnimal)
{
DoThingWithCat(anAnimal); // this is NOT always OK, because we
// DO NOT know the type of anAnimal,
// and it may not be a Cat
}
这也是不安全的,因为它是直接铸造,不一定是向上铸造或向下铸造
public void DoSomethingDifferent(object anObject)
{
DoThingWithAnimal(anObject); // this may or may not work,
// depending on the type passed in,
// this is a recipe for disaster,
// because may not be an Animal,
// it could be a Tree.
}
答案 4 :(得分:0)
迈赫达德给出了正确的答案。只是为了更清楚:
Test
<{1}} - 反之亦然:Program
在您的案例中是Program
。因此,你要做的不是向上,而是不允许。