#flash #actionscript-3
#flash #actionscript-3
Вопрос:
У меня возникли некоторые проблемы с пониманием того, как дочерний элемент может ссылаться на переменные родителей.
Вот мой Main.as :
package
{
import flash.display.MovieClip;
public class Main extends MovieClip
{
public var i;
public var child: Child;
public function Main()
{
i = 4;
child = new Child;
}
}
}
И вот мой Child.as:
package
{
import flash.display.MovieClip;
public class Child extends MovieClip
{
public function Child()
{
trace([parent as MovieClip].i);
}
}
}
дочерний элемент пытается получить доступ к общедоступной переменной i в родительском элементе, но я получаю сообщение об ошибке:
не определено
Используя trace(MovieClip(parent).i) вместо этого я получаю:
Ошибка TypeError: ошибка # 1009: не удается получить доступ к свойству или методу нулевой ссылки на объект. в дочернем () в Main()
Я чувствую, что мне не хватает чего-то довольно фундаментального (например, мне не было задано значение к моменту создания дочернего элемента), но я не могу понять, что.
Разъяснения были бы весьма признательны.
Ответ №1:
parent
Свойство a DisplayObject
устанавливается при его добавлении к другому DisplayObjectContainer
через .addChild()
or .addChildAt()
. Эти вызовы выполняются неявно пользовательским интерфейсом Flash для добавления дочерних элементов к видимому объекту.
Итак, в том, что вы делаете, есть несколько ошибок, некоторые из которых связаны с неправильным пониманием того, как DisplayObjects
работать во flash, а другие — с синтаксическими проблемами.
При вызове вы new Child()
вызываете конструктор Child
классов, в вашем случае:
public function Child()
{
trace([parent as MovieClip].i);
}
На данный момент он не был добавлен как дочерний в a DisplayObjectContainer
. Простое присвоение ему имени a child
в вашем родительском классе не создает эту связь. Таким образом, в этом случае внутри вашего конструктора this.parent
всегда будет null, потому что он просто создает новый экземпляр Child
класса, он не знает ни о каком «родителе»
Здесь также есть довольно большая проблема с синтаксисом. Вы выполняете как as
приведение (которое вернет null
, если типы несовместимы). В этом случае, однако, parent
уже null
есть , но тогда вы используете []
, что является способом записи литерала Array
. Таким образом, вы, по сути, создаете новый Array
с одним элементом, который есть null
. Затем вы пытаетесь получить свойство, вызываемое i
для Array
не родительского.
Очевидно, это не то, что вы хотите сделать… Вообще. Вероятно, вы имели в виду что-то вроде этого:
public function Child()
{
trace((parent as MovieClip).i);
}
Но даже это неверно, потому i
что это не свойство a MovieClip
, а свойство вашего подкласса Main
. Так что вы, вероятно, действительно имели в виду:
public function Child()
{
trace((parent as Main).i);
}
Но это все равно не удастся, потому что, как я уже говорил ранее, parent == null
потому что он еще не был добавлен как дочерний.
Рассмотрим следующий код:
public class Main extends MovieClip
{
public var i;
public var child:Child;
public function Main()
{
i = 4;
child = new Child();
child.doWork();
this.addChild(child)
child.doWork();
}
}
И:
public class Child extends MovieClip
{
public function Child()
{
doWork();
}
public function doWork()
{
if(parent == null) {
trace("No parent yet.")
return;
}
var mainParent:Main = (parent as Main);
if(mainParent == null) {
trace("Parent isn't a instance of Main!")
return;
}
trace(mainParent.i);
}
}
Это должно вызвать метод doWork()
три раза: один раз в дочернем конструкторе, затем перед добавлением в дерево отображения и, наконец, после добавления в дерево отображения. И, надеюсь, это будет иметь больше смысла, если посмотреть, как это работает.
Еще многое предстоит узнать, особенно о событиях, потоке событий и о том, как и связаны / вложены. DisplayObjects
DisplayObjectContainers
Но, возможно, это подтолкнет вас в правильном направлении. Просто знайте, что parent
это просто свойство a DisplayObject
(один из предков MovieClip
и многих других классов во flash). Понимание того, как эти классы работают друг с другом, и расширение их собственной функциональностью — ключ к настоящему пониманию flash.
Комментарии:
1. Вау, спасибо за ваш невероятно исчерпывающий ответ, 32bitkid. Недавно я начал изучать as3, имея небольшой опыт работы с C — код, который я написал в 1-м ключевом кадре на временной шкале, обычно делал то, что я хотел. Однако сегодня я подумал, что попробую выяснить, как использовать файлы extenal .as и разделить их, но это был полный сбой (пока вы не ответили). Итак, еще раз спасибо, что нашли время написать потрясающий ответ, вы сделали мой день!
Ответ №2:
В основном parent не устанавливается, пока вы не вызовете метод addChild, поэтому:
public class Main extends MovieClip
{
public var i;
public var child: Child;
public function Main()
{
i = 4;
child = new Child;
addChild(child);
}
}
конечно, это означает, что parent недоступен и будет не определен в вашем конструкторе. Иногда я передаю родительский элемент, к которому я хочу добавить дочерний элемент, в аргументы конструктора, чтобы упростить добавление вместе с позицией x / y, если это уместно.
public class Child extends MovieClip
{
public function Child(targetParent:DisplayObjectContainer = null, xpos:Number = 0, ypos:Number = 0)
{
if (targetParent != null)
{
targetParent.addChild(this);
}
this.x = xpos;
this.y = ypos;
}
}
Комментарии:
1. Спасибо за ваш ответ, ястребы! Я полностью забыл о addChild (и, следовательно, сбой конструктора)