Assign super to variable in AS3

2019-09-08 23:16发布

问题:

I have this:

public class Base {
    public function whoAmI() {
        trace("base");
    }
}

public class Extended extends Base {

    public function Extended() {
        this.whoAmI() //prints extended
        super.whoAmI() //prints base

        var test = super;
        test.whoAmI() //prints extended
    }

    public override function whoAmI() {
        trace("extended");
    }
}

The problem is when I do var test = super, it seems like this is assigned to test instead of super.

Is it possible to do the assignment so that test.whoAmI() prints "base"?

Edit: In the comments it is being said that using super in the way I propose would break overriding. I don't think that's the case. The way I am thinking of it, super could be used the same way as this. I understand that is not the way super is implemented, but using it that way would not break overriding as people are claiming. So for example the same way this is possible:

var test = this;
test.whoAmI();

This should be possible:

var test = super;
super.whoAmI();

It is obviously the choice of the language implementer to not do things this way, and I don't understand the reason why. It doesn't break things, but I guess it does make them more complicated.

I am not suggesting type-casting this to the super class. Obviously that wouldn't work.

回答1:

You are thinking of "this" and "super" as 2 different instances, 2 different things but they in fact point to the same object (obviously) so at the end it's always "this". Using super is just a special keyword that allows the instance to point to the overrided definitions up the inheritance chain, it does not point to a different object. So "super" does correctly its job, it points to the instance and allow you each time you use it to access overrided definitions and that's it. There's of course no point on trying to store that keyword in a variable since in that case it just return correctly the instance it points to which is always "this". It's simply a case of misunderstood inheritance principle and I've seen it before, super is mistaken for some kind of instance wrapper up the inheriatnce chain around the object "this" while it's in fact and always the same object.



回答2:

No, this is not possible.

If this were possible, then overriding methods wouldn't be possible!


For example, take this function...

public function test(a:Object):void {
    trace(a.toString());
}

You'd only get [object Object] back if your idea was how things worked.



回答3:

Ok I understand what you mean your question is more about language definition and specification.

Look at this exemple in c# that explain how you can manage more precisely overriding in c# :

http://www.dotnet-tricks.com/Tutorial/csharp/U33Y020413-Understanding-virtual,-override-and-new-keyword-in-C

But let's explain a litlle how it's work.

when you extend a class, it's like if you create an object composed of all the object in the inheritance tree so if B extends A and C extends B you have two objects like this:

(B+A) and (C+B+A) with hierarchy between each other B->A and C->B->A. Super is just a way to ascend in the hierachy.

When you cast a C in A for example. In memory you always have an object (C+B+A) but interpreted as A. When you override you just say that a method in child has an higher priority than in parent.



回答4:

You can try downcasting this manually to any of your class's predecessors. The pointer will still be equal to this but the methods called will use the class table of the class used to downcast.

public class Extended extends Base {

    public function Extended() {
        this.whoAmI() //prints extended
        super.whoAmI() //prints base

        var test:Base = this;
        test.whoAmI() //should print base
    }

    public override function whoAmI() {
        trace("extended");
    }
}

Should your Base extend something, which methods are known or the superclass is dynamic, and there is code that adds methods to prototype of a class, you might use such a downcast to call a superclass's method that might not be there at compile time, but make sure you first call hasOwnProperty in case of a dynamic class to determine whether a method or property exists.