在AS3中,库符号是否可以扩展另一个库符号,假设每个符号链接到一个类?

时间:2010-12-09 22:35:09

标签: actionscript-3 inheritance flash-cs4 symbols

例如:

  1. 库符号“Card”链接到扩展“MovieClip”的类“Card”。库符号“卡”包含卡背景图像。
  2. 库符号“Ace”链接到“Ace”类,它扩展了类“Card”。库符号“Ace”包含一个带有大字母“A”的TextField。
  3. 所以我们有Ace扩展卡,它扩展了MovieClip。因此,Ace扩展了MovieClip,但没有直接扩展MovieClip。

    当我在舞台上放下Ace的一个实例并编译剪辑时,所有显示的都是大字母A.但是,我希望包含来自Card的背景图像,因为Ace扩展了Card,而且卡符号包含背景。

    Flash似乎忽略了符号内容,除非它属于要实例化的顶级类。我认为一个符号不能扩展另一个符号。 IDE可以轻松地将Card作为不可编辑的背景绘制,而我正在编辑扩展它的Ace,它应该实例化Card的内容,然后在实例化Ace时实例化Ace的内容。想法?

4 个答案:

答案 0 :(得分:1)

是的,我试过这样做。从理论上讲,您希望每个扩展类的显示列表都可以堆叠,但它们不会 - 它就像您描述的那样工作,您只能看到与最新类关联的图形。

但这对您来说不是一个交易破坏者 - 您可以使用各种建筑选项。例如,您可以创建一个CardBackground类,该类从库中导出并具有卡片形状等。然后,您创建一个具有background:CardBackground属性的Card类。然后您的Ace类可以扩展卡,它应该具有所需的背景。

从技术上讲,你应该支持组合优于继承,但Flash确实鼓励继承思维。一旦你习惯了突破,你就会意识到可以用所描述的方式使用组合创建更强大,更健壮的类。

欢呼,我希望有所帮助!

答案 1 :(得分:1)

card_mc(Card movieclip)的基类可能是您的Card类,但它不会使您的Card类与card_mc同义。

尝试这样做:

1)创建一个包含卡片背景图片的动画片段,并将其命名为cardSprite_mc。给它类名CardSprite并将其基类设置为flash.display.Sprite。

2)创建一个包含字母“A”的文本字段的movieclip,并将其命名为ace_mc。给它类名为Ace,基类为com.cards.Ace。

3)使用以下代码创建一个名为Card的类:

package com.cards
{
    import flash.display.Sprite;

    public class Card extends Sprite
    {
        public function Card():void 
        {
            addChildAt(new CardSprite(), numChildren - 1);

        }// end function

    }// end class

}// end package

4)使用以下代码创建一个名为Ace的类:

package com.cards
{
    import com.cards.Card;

    public class Ace extends Card
    {
        public function Ace():void 
        {

        }// end function

    }// end class

}// end package

现在,如果您在舞台上添加Ace实例,您也应该看到卡片背景图片。

我希望这有助于:)

答案 2 :(得分:0)

你不能以程序化的方式做到这一点。

相反,您必须使用Flash Authoring环境。通过创建一个包含其中基本符号的符号来扩展符号。

而且,是的,我同意,这很有名。

答案 3 :(得分:0)

Taurayi的解决方案很有启发性,因为它确定了从Class到Symbol缺少显式链接,确保Symbol的内容被实例化,无论它是顶级类还是仅仅是基类在继承链中。然而,这种方法的副作用是它在Card的内容中添加了额外的包含级别,即CardSprite容器。

我设法实现了一个实用的通用解决方案,它实际上保留了所有继承符号的预期堆叠行为。例如,如果你检查" numChildren"在下面的Symbol2实例中,它将完全是Symbol1.numChildren和Symbol2.numChildren的总和,因此它是符号内容的真正合并堆叠。

当您的符号位于继承链中时,只需添加此" ensureLinkage"在调用super()方法后随时调用。

package
{
    public class Symbol1 extends Sprite
    {
        public function Symbol1()
        {
            super();
            BugFixes.ensureLinkage( this, "Symbol1" );
        }
    }
}


package
{
    public class Symbol2 extends Symbol1
    {
        public function Symbol2()
        {
            super();
            BugFixes.ensureLinkage( this, "Symbol2" );
        }
    }
}

注意:不要忘记确保您的顶级符号也明确定义了具有上述模式的类。

当Symbol2和Symbol1链接到库中的相应符号时,它们的内容现在将堆叠。只需在舞台上放一个Symbol2实例,然后测试一下电影。您会看到Symbol1的内容显示在Symbol2的内容下。 (注意:设计器中没有出现,因为这是运行时修复)。

ensureLinkage的实施如下:

package
{
    import flash.utils.getQualifiedClassName;
    import flash.utils.getDefinitionByName;
    import flash.events.Event;

    public class BugFixes
    {

        public static var linkageMonitor:Object = new Object();
        private static var linkageMonitorAuthority:Array = new Array();

        public function BugFixes()
        {
        }

        public static function ensureLinkage( instance:*, className:String )
        {
            if (getQualifiedClassName( instance ) != className) //detect non-top-level construction
            {
                //prevent inevitable factorial-recursive construction
                var stack:Array = linkageMonitor[instance] as Array;
                if (stack == null)
                {
                    stack = new Array();
                    stack["numChildren"] = instance.numChildren;
                    linkageMonitor[instance] = stack;
                }

                var barredByAuthority:Boolean = false;
                if (linkageMonitorAuthority.length > 0)
                    barredByAuthority = (linkageMonitorAuthority[linkageMonitorAuthority.length - 1] as Array).indexOf( className ) > -1;
                if (stack.indexOf( className ) == -1 && !barredByAuthority)
                {
                    stack.push( className ); //remember construction
                    trace( "ensuring Linkage of inherited class " + className );

                    //perform top-level construction to trigger symbol linkage and child object instantiation
                    linkageMonitorAuthority.push( stack );
                    var temp:* = new (getDefinitionByName( className ) as Class)();
                    linkageMonitorAuthority.pop();

                    //Merge children
                    while (temp.numChildren > 0)
                        instance.addChild( temp.getChildAt( 0 ) );

                    //Merge properties
                    for (var prop:String in temp)
                        instance[prop] = temp[prop];
                }
                else
                {
                    trace( "skipping redundant construction of: " + className );
                }
            }
            else
            {
                var stack:Array = linkageMonitor[instance] as Array;
                if (stack != null)
                {
                    var nc:int = int(stack["numChildren"]);
                    trace("construction completing for " + getQualifiedClassName( instance ) );
                    for (var i:int = 0; i < nc; i++)
                        instance.setChildIndex( instance.getChildAt( 0 ), instance.numChildren - 1 );
                }
                delete linkageMonitor[instance]; //top-level constructor is completing, all relevant sub-objects have been constructed
            }
        }
    }
}

基本上,它通过查看实例的限定类名是否与从类本身传递给调用的预期类名匹配来检测符号是否需要手动实例化。由于它是在&#34; super&#34;之后调用的,所以调用从最深的类开始,并通过创建一个临时的顶级实例并声明其子代为其实例来确保其库符号的子代实例化。拥有。对实例的第一次调用也会抓取原始子节点数,因为堆栈中的顶级剪辑在任何构造函数代码运行之前都已经实例化了它的子节点。通过存储该数字,最后一步可以将这些初始孩子拉到他们所属的顶部。通过使用&#34;权限&#34;该类确保不会发生不必要的递归。堆栈以确保主堆栈始终对子构造函数可见。

一个问题是静态笔画没有被保留,但这只是因为AS3没有提供用于访问笔画的API(即一旦你在设计器中绘制一条线,或者使用graphics.lineTo,就没有办法以编程方式访问它用于枚举或修改目的的笔划,但一次清除所有笔划除外)。因此,这不是此方法的限制,而是Flash的API。

也许Adobe根本无法想出这个实现:P

请注意,如果您的符号执行将符号实例与其他代码绑定的任何工作,则可能存在问题,因为此类声明来自临时实例的子项的所有权。它还使用for循环声明来自临时实例的变量引用的值,但是在这样的泛型实现中它是最好的。