AS3 Ссылка на подкласс подкласса из родительского без создания экземпляра? - PullRequest
2 голосов
/ 01 мая 2011

Могу ли я получить доступ к статической переменной подкласса подкласса?Я не хочу создавать его экземпляр, просто ищу переменную, потому что она уже инициализирована подклассом.

пример:

package
{
    public class A extends MovieClip {
        private var classB:B = new B();

        public function A() {
            //**ACCESS B.C.MYVAR**
        }
    }
}

package
{
    public class B extends MovieClip {
        private var classC:C = new C();
    }
}

package
{
    public class C extends MovieClip {

        public static var MYVAR = 1;
    }
}

Спасибо!

Ответы [ 3 ]

1 голос
/ 01 мая 2011

Ответ на этот вопрос уже принят, но мой ответ на вопрос, заданный Тимом Джойсом в его комментарии к принятому ответу:

Спасибо за ответ, Марти, что о вызове публичного вар от C, что не статичен? Это возможно? Какие У меня есть событие, отправленное из B дать мне знать, что С изменился, но я нужно получить переменную в C от А, когда событие отправляется. Человек, я надеюсь, вы можете понять, что Я только что написал.

Ниже приведено небольшое приложение, которое я создал для ответа на этот вопрос:

package 
{
    import flash.display.Sprite;
    import flash.events.Event;

    public class Main extends Sprite 
    {
        private var _popcornMicrowave:PopcornMicrowave;

        public function Main():void 
        {
            if (stage) init();
            else addEventListener(Event.ADDED_TO_STAGE, init);

        }// end function

        private function init(e:Event = null):void 
        {
            removeEventListener(Event.ADDED_TO_STAGE, init);

            // 1 minute and 30 seconds
            var delay:Number = PopcornMicrowave.MINUTE + (PopcornMicrowave.SECOND * 30);

            _popcornMicrowave = new PopcornMicrowave(delay);

            trace(_popcornMicrowave.popcorn.isReady); // output: false

            _popcornMicrowave.startTimer();

            _popcornMicrowave.addEventListener(Event.COMPLETE, onPopcornMicrowaveComplete);

        }// end function

        private function onPopcornMicrowaveComplete(e:Event):void
        {
            _popcornMicrowave.removeEventListener(Event.COMPLETE, onPopcornMicrowaveComplete);

            trace(_popcornMicrowave.popcorn.isReady) // output: true

        }// end function

    }// end class

}// end package

import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.TimerEvent;
import flash.utils.Timer;

internal class PopcornMicrowave extends EventDispatcher
{
    public static const SECOND:Number = 1000;
    public static const MINUTE:Number = SECOND * 60;

    private var _popcorn:Popcorn;
    private var _timer:Timer;

    public function get popcorn():Popcorn { return _popcorn }

    public function PopcornMicrowave(delay:Number = MINUTE) 
    { 
        _popcorn = new Popcorn();
        _timer = new Timer(delay, 1);

    }// end function

    public function startTimer():void
    {
        if (!_timer.running)
        {
            _timer.addEventListener(TimerEvent.TIMER_COMPLETE, onTimerComplete);
            _timer.start(); 

        }// end if

    }// end function

    private function onTimerComplete(e:TimerEvent):void
    {
        _timer.removeEventListener(TimerEvent.TIMER_COMPLETE, onTimerComplete);

        _popcorn.setIsReady(true);

        dispatchEvent(new Event(Event.COMPLETE));

    }// end function

}// end class

internal class Popcorn
{
    private var _isReady:Boolean;

    public function get isReady():Boolean { return _isReady }

    public function Popcorn() { }

    internal function setIsReady(boolean:Boolean):void 
    { 
        _isReady = boolean 

    }// end function

}// end class
1 голос
/ 02 мая 2011

На статическую переменную можно легко ссылаться откуда угодно. Будь то суперкласс, обращающийся к одному из своих подклассов (или sub-sub -...- class), или совершенно другой класс, зависящий от рассматриваемой статической переменной, вы можете получить к нему доступ следующим образом:

public function someFunction():void {
  //Direct Access: Most typical way - accessing a public static var / const,
  //your local-variable should match the data-type of the static
  //variable you're accessing.
  var localVar:String = ClassName.StaticVarName;

  //Dynamic Access: An alternative that can be handy for verifying
  //variables that exists, and then use them once confirmed:
  if(ClassName["StaticVarName"]!=null) {
     trace("Found value: " + ClassName["StaticVarName"]);
  }

  //Iterative Access: If you're looking to iterate through each static
  //variables of a certain class, you can collect those by accessing its
  //description XML document (E4X access that is).
  var classDescription:XML = describeType(ClassName);
  var classVarNames:XMLList =    classDescription.variable.attribute("name");
  for each(var classVarName:String in classVarNames) {
     trace("Found class var: " + classVarName);
  }
}

Теперь, чтобы получить доступ к переменным экземпляра, скрытым на несколько уровней в вашей иерархии классов, вы можете попробовать что-то вроде этого:

// File: A.as
package {
    public class A {
        public function A() {

        }

        public function doSomething():void {
            switch(Object(this).constructor) {
                case B: trace( B(this).methodOnlyInB() ); break;
                case C: trace( C(this).variableOnlyInC ); break;
                default: trace("You are simply in 'A'!"); break;
            }
        }
    }
}

// File: B.as
package {
    public class B extends A {
        public function B() {
            super();
        }

        public function methodOnlyInB():String {
            return "You are calling a 'B' method!";
        }
    }
}

// File: C.as
package {
    public class C extends B {
        public var variableOnlyInC:String = "You are tracing a 'C' variable";

        public function C() {
            super();
        }
    }
}

// File: TestABC.as
var a:A = new A();
var b:B = new B();
var c:C = new C();

a.doSomething();  //Should trace: You are simply in 'A'!
b.doSomething();  //Should trace: You are calling a 'B' method!
c.doSomething();  //Should trace: You are tracing a 'C' variable!

В этом маршруте есть одна проблема. Это заставит вас писать «плохой код». Суперкласс должен НЕ знать какие-либо бизнесы своего подкласса и что они должны делать при определенных условиях. Это правило, которое в значительной степени каждый шаблон проектирования программирования пытается поощрять (и по уважительным причинам), и нарушение этого правила может в долгосрочной перспективе потребовать больших затрат времени, энергии и усилий.

Ситуации, подобные этой, требуют класса " Controller ". По сути, класс, созданный из другого места, будет нести ответственность за анализ объекта A / B / C (например, аналогично тому, как это делает оператор переключения A.doSomething ()). Это освобождает ваши классы Super & Sub от беспорядка и оставляет гораздо больше места для расширения и твердого кода.

Надеюсь, это отвечает всем вашим потребностям в доступе к переменным! :)

1 голос
/ 01 мая 2011

Чтобы получить доступ к общедоступной статической var, вы можете сделать это из любого места в том же пакете через Class.property.

Таким образом, чтобы получить доступ к MYVAR, который определен в классе C, вы должны использовать C.MYVAR.

Вам не нужно создавать экземпляр класса для доступа к статическим свойствам или функциям внутри него - при условии, что они общедоступны.

Я не рекомендую использовать static , за исключением редких случаев, таких как класс "утилит" или что-то подобное. Хорошим примером является встроенный класс Math.

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

package
{
    public class Elements
    {
        public static const FIRE:String = "FIRE_ELEMENT";
        public static const WATER:String = "WATER_ELEMENT";
        public static const ICE:String = "ICE_ELEMENT";
    }
}

Тогда позже я воспользуюсь этим так:

var myelement:String = Elements.WATER;
...