2010-12-09 3 views
0

:AS3에서는 라이브러리 심볼이 클래스에 링크되어 있다고 가정 할 때 다른 라이브러리 심볼을 확장 할 수 있습니까? 예를 들어

도서관 기호 "카드"가 "무비 클립을"확장 클래스 "카드"에 연결되어
  1. . 라이브러리 심볼 "카드"는 카드 배경 이미지를 포함합니다.
  2. 라이브러리 심볼 "Ace"는 클래스 "Card"를 확장하는 클래스 "Ace"에 링크됩니다. 라이브러리 심볼 "Ace"는 큰 글자 "A"를 가진 TextField를 포함합니다.

그래서 우리는 Ace가 MovieClip을 확장하는 카드를 가지고 있습니다. 따라서 Ace는 MovieClip을 확장하지만 MovieClip을 직접 확장하지는 않습니다.

무대에 Ace의 인스턴스를 놓고 클립을 컴파일하면 A가 큰 문자 A로 표시됩니다. 그러나 Ace가 카드를 확장하고 Card를 확장 한 이후 Card의 배경 이미지가 포함될 것으로 예상했습니다. 기호는 배경을 포함합니다.

플래시가 인스턴스화되는 최상위 클래스에 속하지 않는 한 심볼 내용을 무시하는 것처럼 보입니다. 나는 하나의 상징이 다른 상징을 확장 할 수 없다는 것이 절름발이라고 생각한다. 내가 확장하는 Ace를 편집하는 동안 IDE는 편집 할 수없는 배경으로 카드를 쉽게 그릴 수 있으며 Ace가 인스턴스화 될 때 카드의 내용을 인스턴스화 한 다음 Ace의 내용을 인스턴스화해야합니다. 생각?

답변

0

이 심볼에 클래스에서 명시 적 링크, 기호의 내용을 보장 누락하는 것은이 최상위 클래스 또는 단지 기본 클래스에서인지 인스턴스화되고있는 설정 때문에 Taurayi의 솔루션은 아름답습니다 상속 사슬. 그러나이 접근법의 부작용은 Card의 내용, 즉 CardSprite 컨테이너에 추가 봉쇄 수준을 추가한다는 것입니다.

저는 상속 된 모든 심볼의 예상 스태킹 동작을 실제로 보존하는 실용적인 솔루션을 구현할 수있었습니다. 예를 들어, 아래의 Symbol2 인스턴스에서 "numChildren"을 선택하면 정확히 Symbol1.numChildren과 Symbol2.numChildren의 합계가됩니다. 따라서 심볼 내용의 진정한 병합 스태킹입니다.

심볼이 상속 체인에있는 경우 super() 메소드를 호출 한 후 언제든지이 "ensureLinkage"호출을 추가하면됩니다.

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 
      } 
     } 
    } 
} 

를 기본적으로이 기호는 인스턴스의 클래스 이름이 전달 예상되는 클래스 이름과 일치하는지 여부를 확인하여, 수동으로 인스턴스화해야 할거야 여부를 감지, 클래스 자체에서 호출하십시오. "super"이후에 호출되므로 호출은 가장 깊은 클래스에서 시작하여 라이브러리 심볼의 자식이 일시적인 최상위 인스턴스를 만들고 그 자식을 자신의 것으로 선언함으로써 인스턴스화되도록합니다. 인스턴스의 맨 처음 호출은 생성자 코드가 전혀 실행되기 전에 스택의 최상위 클립이 이미 자식을 인스턴스화하므로 자식의 원래 개수를 가져옵니다. 그 번호를 저장함으로써 마지막 단계는 초기 아이들을 자신이 속한 맨 위로 끌어 올 수 있습니다. 클래스는 "authority"스택을 사용하여 메인 스택이 항상 하위 생성자에게 표시되도록함으로써 불필요한 재귀가 발생하지 않도록합니다.

정적 스트로크는 유지되지 않지만 AS3에서는 스트로크에 액세스하기위한 API가 제공되지 않기 때문에 문제가됩니다 (예 : 디자이너에서 선을 그리거나 graphics.lineTo를 사용하면 프로그래밍 방식으로 액세스 할 수 없습니다. 한 번에 모든 스트로크를 지우는 것을 제외하고 열거 또는 수정 목적을위한 스트로크). 이것이 이러한 접근 방식의 한계가 아니라 플래시의 API입니다.

아마도 어도비는이 구현 가지고 올 단순히 없습니다 : P 당신의 기호는 다른 코드로 심볼 인스턴스를 묶어 어떤 작업을 할 경우이 클래스는 소유권을 주장하기 때문에, 문제가있을 수 있습니다

임시 인스턴스에있는 어린이들. 또한 for 루프를 사용하여 임시 인스턴스에서 변수 참조의 값을 요청하지만 이것이 일반적인 구현에서 할 수있는 최선의 방법입니다.

0

프로그래밍 방식으로는이 작업을 수행 할 수 없습니다.

대신 플래시 제작 환경을 사용해야합니다. 그 안에 기본 심볼을 포함하는 심볼을 생성하여 심볼을 확장하십시오.

그리고 동의합니다. 매우 불만입니다.

1

그래, 나는 그것을 시도했다. 이론 상으로는 각 확장 클래스의 디스플레이 목록이 스택 될 것으로 예상되지만 그렇지 않은 경우 - 설명대로 작동하며 가장 최근 클래스와 관련된 그래픽 만 볼 수 있습니다.

다양한 아키텍처 옵션을 마음껏 사용할 수 있습니다. 예를 들어, 라이브러리에서 내 보낸 CardBackground 클래스를 만들고 카드 모양 등을 사용할 수 있습니다. 그런 다음 CardBackground 속성을 가진 Card 클래스를 만듭니다. 그런 다음 에이스 클래스는 카드를 확장 할 수 있으며 원하는 배경을 가져야합니다.

기술적으로 상속에 비해 구성이 유리하지만 플래시는 실제로 상속 사고 방식을 권장합니다. 일단 빠져 나오면 익숙해지면 설명 된 방식으로 구성을 사용하여 훨씬 강력하고 강력한 클래스를 만들 수 있습니다.

환호, 나는 그것이 도움이되기를 바랍니다!

1

귀하의 card_mc (카드 movieclip)에 대한 기본 클래스는 귀하의 카드 클래스 일 수 있지만 귀하의 Card 클래스는 card_mc와 동의어가 아닙니다.

이 대신 일을보십시오 :

1) 카드 배경 이미지를 포함하는 무비 클립을 만들고 cardSprite_mc를 호출합니다. 클래스 이름에 CardSprite를 지정하고 기본 클래스를 flash.display.Sprite로 설정합니다.

2) 문자 "A"가 포함 된 텍스트 필드가 포함 된 동영상 클립을 만들고이를 ace_mc라고합니다. 클래스 이름 에이스와 com.cards.Ace의 기본 클래스를 지정하십시오.

3) 다음 코드를 사용하여 카드라는 클래스를 만들기 : 에이스의 인스턴스를 추가하면 이제

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

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

     }// end function 

    }// end class 

}// end package 

:

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) 다음 코드로 에이스라는 클래스를 생성 스테이지로 가면 카드 배경 이미지도 볼 수 있습니다.

나는이 :) 도움을 희망

+0

"귀하의 카드 _mc (카드 movieclip)에 대한 기본 클래스는 귀하의 카드 클래스 일 수 있지만 귀하의 카드 클래스는 card_mc와 동의어가 아닙니다." 그 문제는 머리 부분을 못살게 굴지 만, 플래시에서는 "카드"를 인스턴스화 할 때 링크 된 심볼의 내용과 동의어이기 때문에 오해의 소지가 있습니다. 예를 들어 플레이어가 클래스와 심볼을 동일시하기 때문에 두 개의 다른 심볼을 같은 클래스 정의를 상속받을 수 없으며 클래스를 직접 인스턴스화 할 때 인스턴스화 할 심볼의 내용을 알지 못합니다. – Triynko

+0

당신의 접근 방식은 생성자에 명시 적으로 컴포지션 문을 추가함으로써 Class에서 Symbol 로의 명시 적 링크를 생성합니다. 생성자 문은 상속 계층에서 최상위 클래스 또는 기본 클래스로 인스턴스화되는지 여부에 관계없이 항상 호출됩니다. 이 문제는 여전히 수동 구성이므로 CardSprite는 별도의 심볼이므로 "Card"클래스에서 인스턴스에 직접 액세스 할 수 없습니다. 예를 들어 Card.instance_name에 액세스하는 대신 Card.getChildAt (0) .instance_name으로 액세스해야합니다. – Triynko

관련 문제