我正在编写一个使用可扩展UI元素的应用程序,其精确实现是在运行时使用配置确定的。因此,例如,我想显示一个项目列表,根据配置,可以显示为项目符号列表,编号列表,两列列表等。包含应用程序对具体实现一无所知,除了它是一种支持方法调用setItems(items:Array):void
的类型。
所以我设置了一个基类,例如:
package my.stuff {
public class BaseList extends MovieClip {
protected var m_items:Array;
public function BaseList() {
m_items = new Array();
}
public function setItems(items:Array):void {
for (var i:int = 0; i < items.length; i++)
m_items.push(items[i]);
}
}
}
然后我创建了一个专门的实现,例如,两列列表:
package my.stuff {
public class TwoColumnList extends BaseList {
protected var m_columns:Array;
public function TwoColumnList() {
super();
m_columns = new Array();
m_columns.push(new Array());
m_columns.push(new Array());
}
public override function setItems(items:Array):void {
for (var i:int = 0; i < items.length; i++) {
m_items.push(items[i]);
m_columns[i%2].push(items[i]);
}
}
}
}
现在,UI本身在Flash Professional中作为FLA完成,类TwoColumnList作为“文档类”。我将FLA(“发布”)编译到目标SWF,然后我尝试将其加载到应用程序中。通常情况下,我希望这样工作:
public function startLoading(implURL:String):void) {
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.INIT, doneLoadingImpl);
loader.load(new URLRequest(implURL));
}
public function doneLoadingImpl(e:Event) {
var info:LoaderInfo = e.target as LoaderInfo;
var impl:DisplayObject = info.content;
m_containerClip.addChild(impl);
var listImpl:BaseList = impl as BaseList;
impl.setItems(m_allItems);
}
除非这不起作用 - addChild()
工作正常,但转化为BaseList
会产生null
(不是例外 - 仅null
)。我可以将impl
转换为MovieClip
就好了,我也可以将它转发到TwoColumnList
,之后它会很好地投射到BaseList
,就像这样:
...
var listImpl:BaseList = impl as TwoColumnList;
...
这样可行,但它确实违背了整个练习的目的 - 这是不提前知道将来可能创建的特定UI实现。
我在某处读过info.applicationDomain.getDefinition
,但我不能说它会产生任何影响。
在我的日常工作中,我不是一名ActionScript开发人员,我刚刚被要求帮助一些主要开发人员不再与公司合作的项目,我很难过 - 任何帮助都将受到赞赏
答案 0 :(得分:1)
您的问题很可能与加载到不同应用程序域的类有关。如果对象不是您要转换的类的子类,则类型转换返回null - 并且看起来您有两个版本的BaseList彼此“竞争”。
如果是这种情况,您可以通过将SWF显式加载到与主要应用程序域相同的应用程序域中来解决此问题:
var ldrContext : LoaderContext = new LoaderContext ( false, ApplicationDomain.currentDomain );
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.INIT, doneLoadingImpl);
loader.load(new URLRequest(implURL), ldrContext );
但是,特别是在加载外部内容时,您应该使用接口。保持实现分离正是它们的发明。查看this blog page,它解释了为什么在加载外部文件时应该使用接口(还有一个指向接口的更基本信息的链接),顺便说一句,作者似乎遇到了与你类似的问题......; )