Решение Taurayi является вдохновляющим, поскольку оно устанавливает отсутствующую явную связь между классом и символом, обеспечивая создание экземпляра содержимого символа, будь то класс верхнего уровня или просто базовый класс в цепочке наследования.Побочным эффектом этого подхода, однако, является то, что он добавляет дополнительный уровень содержания в содержимое Card, а именно контейнер CardSprite.
Мне удалось реализовать практическое универсальное решение, которое фактически сохраняет ожидаемое поведение стека всехунаследованные символы.Например, если вы отметите «numChildren» для экземпляра Symbol2 ниже, это будет в точности сумма символов Symbol1.numChildren и Symbol2.numChildren, так что это будет истинное объединение содержимого символа.
Когда ваш символнаходится в цепочке наследования, просто добавьте этот вызов «sureLinkage» в любое время после вызова метода 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.(Примечание: не отображается в конструкторе, поскольку это исправление во время выполнения).
РеализацияureLinkage выглядит следующим образом:
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», вызовы начинаются с самого глубокого класса и гарантируют, что дочерние элементы его библиотечного экземпляра создаются путем создания временного экземпляра верхнего уровня и утверждения его дочерних элементов как своих собственных.Самый первый вызов экземпляра также захватывает исходное число присутствующих дочерних элементов, поскольку клип верхнего уровня в стеке уже будет создавать экземпляры своих дочерних элементов до того, как какой-либо код конструктора будет выполнен вообще.Сохраняя это число, последний шаг может затем подтянуть эти начальные дочерние элементы к вершине, к которой они принадлежат.Класс гарантирует отсутствие ненужной рекурсии, используя стек «полномочий», чтобы основной стек всегда был виден дочерним конструкторам.
Одна проблема заключается в том, что статические штрихи не сохраняются, но это только потому, что AS3не предоставляет API для доступа к штрихам (т. е. как только вы рисуете линию в конструкторе или с graphics.lineTo, нет никакого способа программно получить доступ к этому штриху для нумерации или изменения, кроме как для очистки всех штрихов сразу).Так что это не ограничение этого подхода, а скорее API Flash.
Возможно, Adobe просто не смогла придумать эту реализацию: P
Обратите внимание, что если ваши символы выполняют какую-либо работу, связанную сВ экземпляре символа для другого кода может возникнуть проблема, поскольку этот класс требует владения дочерними элементами из временного экземпляра.Он также запрашивает значения ссылок на переменные из временного экземпляра, используя цикл for, но это лучшее, что он может сделать в общей реализации, такой как эта.