什么是“upcast”?

8
我可以看到术语“upcast”与OOP有关,但是在互联网上搜索时找不到精确的定义。
请问有人能解释这个术语的含义以及在什么情况下使用这种技术吗?

我不确定,但我认为这是你将类转换回父类的地方。例如,去阅读任何关于多态性的文章。 - slugonamission
我不能保证我能脱口而出地给出定义,不过我猜@slugonamission是正确的。 - Wug
1个回答

10

从您发布的标签描述中可以了解到:

上转型允许将子类类型的对象视为任何超类类型的对象。

基本上,这意味着您将一个子类实例转换为其父类之一,以下是一个使用伪代码的示例:

class Base {
    function say_hi() { printf("Hello From Base Class\n"); }
}

class Person extends Base {
    function say_hi() { printf("Hello!"); }    // Overridden. Java expects an @Override annotation
}

class Dog extends Base {
    function say_hi() { printf("Woof!"); }    // Again, overridden
}

Base B = new Base();
Base P = new Person();   // Implicit upcast
Dog dog = new Dog();
Base D = (Base)Dog();    // Explicit upcast

B.say_hi(); // Hello from base class
P.say_hi(); // Hello!
D.say_hi(); // Woof!

这种技术在很多情况下都非常有用。一般来说,它定义了一种接口,使您可以对某个类进行子类化,但仍然可以在原始上下文中使用它。比如说你有一个游戏,你会有一个敌人对象。它具有一些共同的功能,例如当前位置、速度、生命值和其他属性。尽管如此,有些敌人移动方式不同,可能播放不同的死亡动画,当然也会以不同的方式绘制。问题是,由于它们具有相同的接口,您不希望为处理每种不同类型的敌人编写特殊代码。

因此,创建一个基本的“敌人”类来包含这些字段和空方法是有意义的,然后扩展它以创建SmallEnemy、EvilEnemy、BossEnemy等具有不同模型和动画的类,并填充空方法。这些“空白”方法也可以称为抽象或纯方法。


一个问题,既然你已经将D强制转换为Base,那么你怎么能访问Dog的say_hi()函数呢?我感到很难理解。你能给我一个具体的例子而不是伪代码吗? - can.
1
我同意你的想法slugonamission,但是你可能应该在伪代码中加入一个提示,即dog和person都扩展自base。 - Dan
@Dan - 哎呀,谢谢提醒。这就是早上写代码的后果。 - slugonamission
@can - 抱歉,我错过了你的问题。在这种情况下,您正在当前对象上调用 say_hi 方法。因为 D 对象继承自 Base,所以您可以将其强制转换回 Base,但它仍然保留相同的方法,因此您可以这样做而不会出问题。 - slugonamission
此外,这是使用跳转表实现的。想象一下,您的类带有一个方法表。对于 Dog,该表具有与 Base 相同的格式,但我已更改其中一个条目,因此当我将其强制转换为 Base 时,即使一个单元格的实际内容不同,我仍然可以使用现有的方法表。 - slugonamission

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接