AS3从父类引用子类的子类而不实例化?

发布于 2024-11-04 08:29:36 字数 470 浏览 2 评论 0原文

我可以访问子类的子类的静态变量吗?我不想实例化它,只是想获取变量,因为它已经由子类初始化了。

例如:

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

谢谢!

Can I access a static variable of a subClass' subClass? I don't want to instantiate it, just looking to get the variable because it has already been initialized by the subClass.

example:

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

Thank you!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

失而复得 2024-11-11 08:29:36

要访问 public static var,您可以通过 Class.property 从同一包中的任何位置执行此操作。

因此,要访问 C 类中定义的 MYVAR,您可以使用 C.MYVAR。

您不需要创建类的实例来访问其中的静态属性或函数 - 只要它们是公共的即可。

我不建议使用静态,除非在极少数情况下,例如“实用程序”类或类似的东西。一个很好的例子是内置的 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;

To access a public static var you can do so from anywhere within the same package via Class.property.

So to access MYVAR that's defined in Class C, you would use C.MYVAR.

You don't need to create an instance of a class to access static properties or functions within it - so long as they are public.

I don't recommend using static except for in rare cases such as a "utilities" class or something similar. A good example is the Math class that's inbuilt.

I mostly use static in a class that holds constants, like this example:

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

Then later I make use of this like so:

var myelement:String = Elements.WATER;
╰◇生如夏花灿烂 2024-11-11 08:29:36

这个问题的答案已经被接受,但我的回答是为了回应蒂姆·乔伊斯在对已接受答案的评论中提出的问题:

谢谢你的回答,马蒂,什么
关于从 C 调用公共变量
不是静态的吗?这可能吗?什么
我有一个从 B 发送的事件
让我知道 C 改变了,但我
需要检索C中的变量
事件派发时从 A 开始。
伙计,我希望你能明白什么
我刚刚写了。

以下是我为回答该问题而创建的一个小型 Flash 应用程序:

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

An answer has already been accepted for this question but my answer is in response to the question asked by Tim Joyce in his comment for the accepted answer:

Thanks for the answer Marty, what
about calling a public var from C that
is not static? Is this possible? What
I have is an event dispatched from B
to let me know that C changed but I
need to retrieve the variable in C
from A when the event is dispatched.
Man I hope you can make sense of what
I just wrote.

The following is a small flash application I created to answer that question:

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
冷夜 2024-11-11 08:29:36

静态变量可以轻松地从任何地方引用。无论它是访问其子类之一的超类(或子子类...类),还是依赖于相关静态变量的完全不同的类,您都可以通过以下方式访问它:

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() 的 switch 语句执行此操作的方式)。这可以释放您的 Super &子类避免了混乱,并为扩展和可靠的代码留下了更多的空间。

希望这能满足您所有的变量访问需求! :)

A static variable can easily be referenced from anywhere. Whether it'd be a super-class accessing one of it's subclass (or sub-sub-...-class), or a completely different class dependent on the static variable in question, you can access it this way:

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

Now, in order to access instance variables buried a few levels down in your Class hierarchy, you can try something like this:

// 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!

There is one bit of "issue" going down this route. This will make you write "poor code". A Super-Class should NOT know any of it's sub-classes business and what they should do under certain conditions. Its a rule that pretty much every programming design pattern try to encourage (and for good reasons), and violating this rule can cost a lot of time, energy and hair-pulling in the long run.

Situations like this calls for a "Controller" class. Basically a class, instantiated from elsewhere will have the responsibility to analyze the A/B/C object (ex: similarly to how A.doSomething()'s switch statement does this). This frees up your Super & Sub classes from clutter and leaves much more room for expansion and solid code.

Hope this answers all your variable access needs! :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文