кастинг между классами братьев и сестер, AS3 - PullRequest
0 голосов
/ 17 июня 2010

У меня есть два класса, derivedClassA и derivedClassB, которые оба расширяются parentClass Я объявляю var o:parentClass, а затем, в зависимости от того, что происходит, я хочу разыграть o как тип derivedClassA или derivedClassB.

По сути, это:

var o:parentClass  

...  

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

Но это не работает, я получаю всевозможные ошибки.Разве не так работает наследование классов?Я чувствую, что упускаю что-то действительно фундаментальное, но не могу понять, что.Я должен использовать интерфейсы вместо этого?Есть ли другой способ сделать то, что я хочу?

РЕДАКТИРОВАТЬ ДЛЯ УТОЧНЕНИЯ:
- doSomething() определен в parentClass как открытый, а в производных классах как override public function doSomething()
- ошибкиЯ получаю «Вызов возможно неопределенного метода doSomething через ссылку со статическим типом parentClass».и «Неявное приведение значения типа derviedClassA к несвязанному типу parentClass»

Ответы [ 3 ]

1 голос
/ 29 марта 2011

Я делал это раньше: выбрасывать ошибку в том, что подразумевается как виртуальная функция в базовом классе, чтобы указать на нее при ошибочном вызове. Я делаю это, когда создаю абстрактные базовые классы.

Main.as (Класс документа)

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!");
        }
    }
}
0 голосов
/ 29 марта 2011

Конкретный ответ на заданный вами вопрос таков:

o["doSomething"]();

Однако я не могу рекомендовать вам это сделать. Я думаю, что реальная проблема заключается в том, что ваш родительский класс должен определять doSomething (), тогда производные классы должны переопределять функцию.

0 голосов
/ 17 июня 2010

Я бы сделал интерфейс, чтобы иметь возможность делать то, что вы просите.Это вам не нужно приводить переменную, и это даст вам доступ к вашей функции doSomething.Вот небольшой пример использования вашей структуры: Обратите внимание, что все классы находятся в одном корневом пакете, следовательно, нет операторов импорта.

MainApp.as (это приложение по умолчанию)

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

Как видите, используя интерфейс, вы вызываете функцию doSomething без приведения.Нет проблем с приведением переменных, но это может дать вам более структурированный код, и это гарантирует, что у вас есть метод doSomething в классах, которые реализуют интерфейс.Надеюсь, это поможет ... Удачи

...