user368652
user368652

Reputation: 1

casting between sibling classes, AS3

I have two classes, derivedClassA and derivedClassB which both extend parentClass I'm declaring var o:parentClass and then, depending on what's going on, I want to cast o as either being of type derivedClassA or derivedClassB.

Essentially, this:

var o:parentClass  

...  

if(shouldUseA)  
    o = new derivedClassA();  
else  
    o = new derivedClassB();  
o.doSomething();

But it's not working, I'm getting all sorts of errors. Isn't this how class inheritance works? I feel like I'm missing something really fundamental, but I can't figure out what. Am I supposed to be using interfaces instead? Is there another way of doing what I want?

EDIT FOR CLARIFICATION:
- doSomething() is defined in parentClass as public, and in the derived classes as override public function doSomething()
- errors I'm getting are "Call to a possibly undefined method doSomething through a reference with static type parentClass." and "Implicit coercion of a value of type derviedClassA to an unrelated type parentClass"

Upvotes: 0

Views: 991

Answers (3)

Adam Smith
Adam Smith

Reputation: 1937

I've done this before: throw error in what is meant to be a virtual function in the base class, to obviously point out when mistakenly calling it. I do this when I make abstract base classes.

Main.as (Document Class)

package
{
    import flash.display.Sprite;

    public class Main extends Sprite
    {
        private var superClassRef:SuperClass;
        private var idLikeToBuyAnA:Boolean = true;

        public function Main()
        {
            trace("Main()");
            if (idLikeToBuyAnA)
            {
                superClassRef = new DerivedClassA();
            }
            else
            {
                superClassRef = new DerivedClassB();
            }

            superClassRef.doSomething();
        }
    }
}

SuperClass.as

package
{
    public class SuperClass
    {
        public function SuperClass()
        {
        }

        public function doSomething():void
        {
            throw new Error("Override me, I wish I were virtual!");
        }
    }
}

DerivedClassA.as

package
{
    public class DerivedClassA extends SuperClass
    {
        public function DerivedClassA()
        {
        }

        override public function doSomething():void
        {
            trace("I'm and A!");
        }
    }
}

DerivedClassB.as

package
{
    public class DerivedClassB extends SuperClass
    {
        public function DerivedClassB()
        {
        }

        override public function doSomething():void
        {
            trace("I'm a B!");
        }
    }
}

Upvotes: 1

Dusty J
Dusty J

Reputation: 721

The specific answer to the question you asked is this:

o["doSomething"]();

However, I can't recommend that you do that. I think the real issue is that your parent class should define doSomething(), then the derived classes should override the function.

Upvotes: 0

a--m
a--m

Reputation: 4782

I would make a Interface to be able to do what you are asking for. This you you don't have to cast the variable, and it will give you access to your doSomething function. Here is a small example using your your structure: Note that all the classes are in the same root package, hence there is no import statements.

MainApp.as (this is the default application)

package  
{
    import flash.display.Sprite;

    public class MainApp extends Sprite 
    {
        private var parentClass : IParent;
        private var doA : Boolean = false;

        public function MainApp()
        {

            if (doA)
            parentClass = new DerivedClassA();
            else
            parentClass = new DerivedClassB();

            parentClass.doSomething();
        }
    }
}

Parent.as

package  
{
    import flash.display.Sprite;

    public class Parent extends Sprite
    {
        public function Parent()
        {
        }
    }
}

DerivedClassA.as

package  
{
    public class DerivedClassA extends Parent implements IParent
    {
        public function DerivedClassA()
        {
            super();
        }

        public function doSomething() : void 
        {
            trace (this + " done something");
        }
    }
}

DerivedClassB.as

package  
{
    public class DerivedClassB extends Parent implements IParent
    {
        public function DerivedClassB()
        {
            super();
        }

        public function doSomething() : void 
        {
            trace (this + " done something");
        }
    }
}

IParent.as

package  
{
    public interface IParent 
    {
        function doSomething():void;
    }
}

As you can, see using a Interface, you call the function doSomething without the casting. There is no problem about casting variables, but this can give you a more structured code, and it will assure you have the doSomething method in the classes that implement the interface. Hope it helps... G luck

Upvotes: 0

Related Questions