多态性不像我想的那样工作吗?

时间:2009-06-24 21:19:07

标签: inheritance casting polymorphism

我有一个处理汽车贴花信息的超类。我有一个子类来处理事务的特定贴花信息。我在事务贴花中有一个特殊的覆盖,用于在设置贴花#之前检查某些东西。我遇到的问题是,有时我需要获取有关通用贴花对象的信息并将其设置为我的事务贴花。例如:

TransactionDecal myTransactionDecal = new TransactionDecal();
Decal myGenericDecal = new Decal();
myTransactionDecal = (TransactionDecal) myGenericDecal.getGenericDecal();

但是我收到运行时错误,告诉我我不能在类型之间进行转换。我究竟做错了什么,这是正确的方法吗?谢谢!

6 个答案:

答案 0 :(得分:3)

可替代性原则表明任何类型都可以由自身或子类型进行替换。

在这里,你正在反过来 - 你试图在子类型的变量中引用超类型的实例(假设Decal是超类,而TransactionDecal是子类)。

这是被阻止的,因为存在专门化现有类的继承,即扩展接口;通常,替换超类将限制接口,这将允许调用未在超类中实现的方法(通过引用变量类型)。

答案 1 :(得分:1)

你不能这样做,因为你会将不太专业的类(Decal)转换为更特殊的类(TransactionDecal)。这不能正常工作,因为现在你可以在Decal上调用那里没有实现的方法(只考虑可能在新方法或覆盖方法中使用的TransactionDecal中新引入的变量)它们不可能存在在贴花的例子中。

答案 2 :(得分:0)

杰里米解释为什么这不起作用就是钱。

如果你想解决这个问题,你可以让transactionDecal不从Decal继承,而是包含一个Decal实例。这样,您可以将内部实例设置为通用贴花,而不会丢失任何交易数据。

当然还有其他模式,但这是处理此类问题的一种比较流行的模式。

答案 3 :(得分:0)

这称为向下转型。这是一个非常好的quick intro,当它没有问题时,它不是(无论如何都是C#)......

Animal a;
a = b;
Bird b = (Bird) a; // Okay
     

此代码将成功编译。   在运行时,演员操作员   执行检查以确定是否   提到的对象实际上是   类型鸟。如果不是,则为运行时   引发InvalidCastException。

但是,你不应该这样做。您的派生类型应该能够执行基本类型可以执行的所有操作。如果你有一个基类型并且想要只有派生类型可以做的事情,那么你最好得到一个派生类型的实例来做它! :)

每条评论编辑:没有理由你不能提供一个Derived构造函数来获取一个Base实例并构建一个Derived(就像一个特定Base的默认Derived)...

public D(B b)
{
}

但是,听起来我需要一个界面,或者你应该放松对方法参数的要求。毕竟,如果你的方法可以对动物进行操作就好了,没有理由它会强迫你把它交给你的方法似乎正在做的鸟。

答案 4 :(得分:0)

在这里使用你的例子是如何实现多态性的:

// cast derived object as base object
Decal myGenericDecal = null;
TransactionDecal myTransactionDecal = TransactionDecal.GetTransactionDecal()
myGenericDecal = myTransactionDecal;

// cast base object to a derived object
TransactionalDecal newTransactionalDecal = null;
newTransactionalDecal = (TransactionalDecal)myGenericDecal;

答案 5 :(得分:0)

这取决于你想对myTransactionDecal做什么,特别是你是否需要TransactionDecal的数据成员。如何添加构造函数?

TransactionDecal::TransactionDecal(const Decal &);

或者只是将您想要的功能移到Decal中,或者转移到非成员函数中?