Flash as3 ссылается на родительские переменные с потомком - PullRequest
0 голосов
/ 31 октября 2011

У меня возникли некоторые проблемы, связанные с тем, как ребенок может ссылаться на переменные родителей.

Вот мой 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);
        }
    }
}

child пытается получить доступ к публичной переменной i в родительском файле, но я получаю сообщение об ошибке:

неопределенный

Используя вместо этого trace (MovieClip (parent) .i), я получаю:

TypeError: Ошибка # 1009: невозможно получить доступ к свойству или методу с нулевым значением ссылка на объект. у ребенка () у главного ()

Я чувствую, что упускаю что-то довольно фундаментальное (как будто я не установил значение к моменту создания дочернего элемента), но я не могу понять, что.

Разъяснение будет высоко ценится.

Ответы [ 2 ]

1 голос
/ 31 октября 2011

Свойство parent для DisplayObject устанавливается, когда оно добавляется к другому DisplayObjectContainer через .addChild() или .addChildAt(). Эти вызовы неявно выполняются пользовательским интерфейсом Flash для добавления дочерних элементов в видимый объект.

Таким образом, в том, что вы делаете, есть некоторые неправильные вещи, некоторые из них неправильно понимают, как DisplayObjects работает во флэш-памяти, а другие - синтаксические проблемы.

Когда вы вызываете new Child(), вы вызываете конструктор классов Child, в вашем случае:

public function Child()
{
    trace([parent as MovieClip].i);
}

На данный момент он не был добавлен как дочерний элемент к DisplayObjectContainer. Простое присвоение ему имени child в родительском классе не создает этих отношений. Таким образом, в этом случае внутри вашего конструктора this.parent всегда будет нулевым, поскольку он просто создает новый экземпляр класса Child, он не знает ни о каком «родительском»

Здесь также есть довольно большая проблема с синтаксисом. Вы делаете как as cast (который вернет null, если типы несовместимы). В этом случае, однако, parent уже равен null, но тогда вы используете [], который является способом для записи литерала Array. Таким образом, вы по существу создаете новый Array с одним элементом, который null. Затем вы пытаетесь получить свойство с именем i на Array, а не на родительском элементе.

Очевидно, это не то, что вы хотите сделать ... Вообще. Вы, вероятно, имели в виду что-то вроде этого:

public function Child()
{
    trace((parent as MovieClip).i);
}

Но даже это не правильно, потому что i не является свойством 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 - это просто свойство DisplayObject (один из предков MovieClip и многих других классов во флэш-памяти). Понимание того, как эти классы работают друг с другом, и расширение их собственной функциональностью - ключ к настоящему пониманию flash.

0 голосов
/ 31 октября 2011

В основном родительский объект не устанавливается, пока вы не вызовете метод addChild, поэтому:

public class Main extends MovieClip
{
    public var i;
    public var child: Child;

    public function Main()
    {
        i = 4;
        child = new Child;
        addChild(child);
    }
}

Конечно, это означает, что родительский элемент недоступен и будет неопределенным в вашем конструкторе.Иногда я передаю родительский элемент, в который я хочу добавить дочерний элемент, в аргументы конструктора, чтобы упростить добавление вместе с позицией 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;
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...