2010-12-09 69 views
0

Par exemple:Dans AS3, un symbole de bibliothèque peut-il étendre un autre symbole de bibliothèque, en supposant que chacun soit lié à une classe?

  1. symbole bibliothèque « carte » est liée à la classe « carte » qui étend « MovieClip ». Le symbole de la bibliothèque "Carte" contient une image de fond de la carte.
  2. Le symbole de bibliothèque "Ace" est lié à la classe "Ace", qui étend la classe "Card". Le symbole de la bibliothèque "Ace" contient un TextField avec une grande lettre "A".

Nous avons donc Ace extends Card qui étend MovieClip. Ace étend donc MovieClip, mais ne prolonge PAS DIRECTEMENT MovieClip. Quand je dépose une instance d'Ace sur la scène et compile le clip, tout ce qui apparaît est la grande lettre A. Cependant, je m'attendais à inclure l'image de fond de Card, puisque Ace étend Card, et la carte le symbole contient l'arrière-plan.

Il semble que Flash ignore le contenu des symboles sauf s'il appartient à la classe de niveau supérieur qui est instanciée. Je pense que c'est LAME qu'un symbole ne peut pas en prolonger un autre. L'EDI pourrait facilement dessiner Card comme un arrière-plan non éditable pendant que je suis en train d'éditer Ace qui le prolonge, et il devrait instancier le contenu de la Carte puis le contenu de l'Ace lorsqu'un As est instancié. Pensées?

Répondre

0

solution de Taurayi est source d'inspiration, car il établit que le chaînon manquant explicite de la classe à Symbole, assurer le contenu du symbole est instancié que ce soit la classe de niveau supérieur ou juste une classe de base une chaîne d'héritage. Un effet secondaire de cette approche, cependant, est qu'elle ajoute un niveau de confinement supplémentaire dans le contenu de Card, à savoir le conteneur CardSprite.

J'ai réussi à implémenter une solution générique pratique qui préserve réellement le comportement d'empilement attendu de tous les symboles hérités. Par exemple, si vous cochez "numChildren" sur une instance de Symbol2 ci-dessous, il s'agira exactement de la somme de Symbol1.numChildren et de Symbol2.numChildren, il s'agit donc d'une véritable fusion de contenu de symbole. Lorsque votre symbole est dans une chaîne d'héritage, ajoutez simplement cet appel "ensureLinkage" à tout moment après un appel à la méthode super(). Remarque: N'oubliez pas de vous assurer que le symbole de niveau supérieur définit également explicitement une classe avec le modèle ci-dessus.

Lorsque Symbol2 et Symbol1 sont liés aux symboles correspondants dans la bibliothèque, leur contenu s'empile maintenant. Il suffit de déposer une occurrence de Symbol2 sur la scène et de tester le film. Vous verrez que le contenu de Symbol1 apparaît sous le contenu de Symbol2. (Remarque: n'apparaît pas dans le concepteur, car il s'agit d'un correctif d'exécution).

La mise en œuvre de ensureLinkage est la suivante:

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

Fondamentalement, il détecte si les symboles auront besoin instancié manuellement, en voyant que le nom de classe qualifié de l'instance correspond au nom de la classe attendue passé à la appel de la classe elle-même. Comme il est appelé après "super", les appels commencent à la classe la plus profonde et s'assurent que les enfants de son symbole de bibliothèque sont instanciés en créant une instance temporaire de premier niveau et en revendiquant ses enfants comme siens. Le tout premier appel de l'instance récupère également le nombre initial d'enfants présents, puisque le clip de premier niveau de la pile aura déjà instancié ses enfants avant que le code du constructeur ne soit exécuté. En stockant ce nombre, une dernière étape peut ensuite amener ces premiers enfants au sommet où ils appartiennent. La classe n'assure aucune récursion inutile en utilisant une pile "autorité" pour s'assurer que la pile principale est toujours visible pour les constructeurs enfants. Un problème est que les traits statiques ne sont pas persistants, mais uniquement parce qu'AS3 ne fournit pas d'API pour accéder aux traits (par exemple, une fois que vous dessinez une ligne dans le concepteur ou avec graphics.lineTo, il n'y a aucun moyen d'accéder par programmation ce coup à des fins de dénombrement ou de modification, sauf pour effacer tous les coups à la fois). Ce n'est donc pas une limitation de cette approche, mais plutôt l'API de Flash.

Peut-être que Adobe était tout simplement incapable de trouver cette mise en œuvre: P

S'il vous plaît noter que si vos symboles font un travail qui lie l'instance de symbole autre code, il pourrait y avoir un problème, étant donné que cette classe revendique la propriété des enfants d'une instance temporaire. Il revendique également les valeurs des références de variables de l'instance temporaire en utilisant une boucle for, mais c'est ce qu'il peut faire de mieux dans une implémentation générique comme celle-ci.

0

Vous ne pouvez pas faire cela de manière programmatique. A la place, vous devez utiliser l'environnement Flash Authoring. Étendre les symboles en en créant un qui inclut le symbole de base à l'intérieur.

Et, oui, je suis d'accord, c'est assez LAME.

1

Oui, j'ai essayé de le faire. En théorie, vous vous attendez à ce que la liste d'affichage de chaque classe étendue soit empilée, mais ce n'est pas le cas - cela fonctionne comme vous le décrivez, où vous ne voyez que les graphiques associés à la classe la plus récente.

Ce n'est pas un problème pour vous, cependant - diverses options architecturales sont à votre disposition. Vous pourriez, par exemple, créer une classe CardBackground qui est exportée hors de votre bibliothèque et qui a la forme de la carte etc. Ensuite, vous créez une classe Card qui a une propriété background: CardBackground. Ensuite, votre classe Ace peut étendre Card et il devrait avoir l'arrière-plan désiré.

Techniquement, vous êtes supposé favoriser la composition par rapport à l'héritage, mais Flash encourage vraiment la mentalité d'héritage. Une fois que vous aurez l'habitude d'en sortir, vous réaliserez qu'il est possible de créer des classes beaucoup plus puissantes et robustes en utilisant la composition de la manière décrite.

Bravo, et j'espère que ça aide!

1

La classe de base de votre card_mc (Card MovieClip) peut être votre classe Card mais elle ne rend pas votre carte Card synonyme de card_mc.

Essayez de faire ceci:

1) Créer une MovieClip contenant l'image d'arrière-plan de la carte et l'appeler cardSprite_mc. Donnez-lui le nom de classe CardSprite et définissez sa classe de base sur flash.display.Sprite.

2) Créez un MovieClip contenant le champ texte contenant la lettre "A" et appelez-le ace_mc. Donnez-lui le nom de classe Ace et une classe de base de com.cards.Ace.

3) Créer une classe appelée carte avec le code suivant:

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) Créer une classe appelée Ace avec le code suivant:

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

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

     }// end function 

    }// end class 

}// end package 

Maintenant, si vous ajoutez une instance de Ace à la scène, vous devriez voir l'image de fond de la carte aussi.

J'espère que cela a aidé :)

+0

"La classe de base de votre card_mc (Card MovieClip) peut être votre classe Card mais elle ne rend pas votre carte Card synonyme de card_mc." Cela cloue le problème sur la tête, mais c'est aussi trompeur, car dans Flash, quand j'instancie "Carte", il * est * synonyme du contenu du symbole qui lui est lié. Par exemple, vous ne pouvez pas avoir deux symboles différents héritant de la même définition de classe, car le joueur assimile la classe au symbole, et ne connaîtrait pas le contenu du symbole à instancier lorsque vous instanciez directement la classe. – Triynko

+0

Votre approche crée ce lien explicite (manquant) de Class à Symbol en ajoutant explicitement une instruction de composition au constructeur, qui est toujours appelée instanciée comme une classe de premier niveau ou comme une classe de base dans une hiérarchie d'héritage. Le problème avec ceci, c'est que c'est encore de la composition manuelle, et comme CardSprite est un symbole séparé, vous ne pouvez pas accéder à ses instances directement sur la classe "Card". Par exemple, plutôt que d'accéder à Card.instance_name, vous devez y accéder en tant que Card.getChildAt (0) .instance_name. – Triynko