我正在设计一个框架,在这个过程中,我遇到了一个有趣但最有可能的基本问题。我有一个名为 CoreEngine 的基类和另外两个扩展它的类: CoreEngine1 和 CoreEngine2 。我创建了一个接口,每个类都会实现这个接口,以增加项目的灵活性。但是,我有一个问题...我在接口中的方法定义与每个继承类中的定义不匹配!每个类必须实现以下方法:
function get avatar():AvatarBase;
问题是 CoreEngine1 和 CoreEngine2 需要不同类型的头像:
CoreEngine1
function get avatar():AvatarScaling
CoreEngine2
function get avatar():AvatarPlatform
如您所见,CoreEngine1和CoreEngine2中头像的返回类型与界面中指定的类型不匹配。我希望由于AvatarScaling和AvatarPlatform都继承了 AvatarBase ,因此编译时不会出现问题。然而,这种情况并非如此。根据Adobe的文档,类型必须与界面匹配。我试图遵循面向对象编程的核心概念之一来扩展我的框架的灵活性:“程序到接口而不是实现”。我想到的第一件事是访问器方法的返回类型应该是一个接口类型(也许我只回答了我自己的问题)。
我确信这是其他人之前遇到的常见问题。在架构上,您认为解决此问题的最佳方法是什么?提前谢谢!
此致
威尔
答案 0 :(得分:1)
这是界面如何工作和声明的限制。
如果返回类型可能会发生继承,正如您在AvatarBase
和子类中所描述的那样,那么我认为正确的方法是使返回类型成为最小公分母并且只处理结果对象在另一端。因此,如果您正在处理CoreEngine1
对象,则表示您可以将结果从AvatarBase
投射到AvatarScaling
。或者,如果您不知道要调用的对象类型get avatar()
,则可以键入检查返回的值。如果您要调用AvatarScaling
上但不在AvatarBase
上的方法,则只需要进行类型检查。在这种情况下,我不认为返回接口类型会给你带来太大的影响,因为接口可以实现的唯一事情就是所有形式的Avatar共享的东西,这与AvatarBase
中的方法没有任何不同。
答案 1 :(得分:1)
与HotN和Dinko提到的一样,最好允许get avatar()
依次返回AvatarBase,然后将返回的对象作为具体子类进行投射。
使用Dinko的例子:
public /* abstract */ class CoreEngine
{
public /* abstract */ function get avatar():AvatarBase {}
}
public function CoreEngine1 extends CoreEngine
{
override public function get avatar():AvatarBase { return new AvatarScaling(); }
}
public function CoreEngine2 extends CoreEngine
{
override public function get avatar():AvatarBase { return new AvatarPlatform(); }
}
public /* abstract */ class AvatarBase {}
public class AvatarScaling extends AvatarBase
{
public function someAvatarScalingMethod():void {}
}
public class AvatarPlatform extends AvatarBase
{
public function someAvatarPlatformMethod():void {}
}
要使用AvatarScaling中的方法,请转换返回的对象:
var c1:CoreEngine1 = new CoreEngine1();
var avatarScaling:AvatarScaling = AvatarScaling(c1.avatar());
avatarScaling.someAvatarScalingMethod();
HTH
答案 2 :(得分:0)
我认为你回答了自己的问题......返回类型仍然是AvatarBase,你需要遵循你在界面中指定的签名......但是你可以在技术上返回该功能中任何AvatarBase的后代。所以做一些像
这样的事情return new AvatarScaling();
CoreEngine1中的是完全可以接受的。
当然,在你的调用函数中,你将获得一个AvatarBase实例,你必须知道这是什么才能转换为特定的子类。
CoreEngine1 ce1 = new CoreEngine1();
AvatarScaling avatar = ce1.avatar() as AvatarScaling;