Правильное использование интерфейсов в Actionscript 3

#actionscript-3 #interface

#actionscript-3 #интерфейс

Вопрос:

Я создал интерфейс под названием iHero, который я реализую в своем классе hero.as3. класс hero написан так, чтобы его можно было наследовать в классе movieclip для обработки движения и т. Д. И т. Д. Но почему-то я не могу понять, как закодировать это с хорошей практикой.

Возможно, я в неправильном направлении.

Я хочу иметь подкласс movieclip, который будет, например, героем.

Должен ли я просто реализовать iHero в классе hero с помощью следующих методов, или это перебор? — Я думаю, я ищу ответ на то, что должно быть в интерфейсе, а что нет. Вот интерфейс.

 package com.interfaces
{
    public interface IHero
    {
        //movement
        function MoveLeft():void;
        function MoveRight():void;
        function MoveUp():void;
        function MoveDown():void;

        //in battle
        function DoDamage(isCasting:Boolean):void;
        function DoHeal():void;
        function Flee():void;
        function TakeDamage():void;
        function IsAlive():Boolean;
        function CheckDeath():void;
        function Die():void;
    }
}
  

Комментарии:

1. Интерфейсы в as3 довольно часто излишни. Это не Java 🙂

Ответ №1:

Я думаю, что вы на правильном пути, независимо от того, правильный он или неправильный, всегда субъективно. Но если вы действительно хотите пойти по этому пути, я предлагаю вам прочитать эту статью Мика Уэста. Ему несколько лет, но он все еще очень применим.

Я думаю, что у вас действительно есть два разных интерфейса, но, вероятно, больше

 public interface IMoveable {
    function moveLeft(obj:DisplayObject):void;
    function moveRight(obj:DisplayObject):void;
    function moveUp(obj:DisplayObject):void;
    function moveDown(obj:DisplayObject):void;
    function Flee(obj:DisplayObject);
}

public interface IFightable {
    function doDamage(withWeapon:IEquipableWeapon);
    function takeDamage(fromWeapon:IEquipableWeapon);
    function get isAlive():Boolean;
    function checkDeath():void;
    function Die():void;
    function doHeal();
    function get health():Number;
}
  

Затем….

 public class SimpleMover implements IMoveable {
    // The movement implementation

    // for example:

    public funciton moveLeft(obj:DisplayObject) {
        obj.x = obj.x -= 10;
    } 
}

public class SimpleFighter implements IFightable {
    // The fighting implementation

    private var _health:Number = 100;

    function doDamage(withWeapon:IEquipableWeapon) {
        _health -= withWeapon.damage;
    }
}
  

Затем вставьте их в свой подкласс MovieClip для вашего Hero .

 public class Hero extends MovieClip {

    private var _mover:IMoveable;
    private var _fighter:IFightable;

    public function Hero(mover:IMoveable, fighter:IFightable) {
        _mover = move;
        _fighter = fighter;
    }

}
  

Здесь вы используете Hero класс как диспетчер компонентов, так и компонент визуализации, что немного противоречит тому, о чем Уэст говорит в статье, но я отвлекся. Но идея заключается в том, что ваш менеджер (the Hero ) становится более или менее оркестратором, проксируя обратные вызовы, к которым применим любой компонент; методы вызова _mover и fighter для выполнения вашей фактической работы.

У такого подхода есть несколько преимуществ и некоторые недостатки. Во-первых, его сложнее настроить; это требует, чтобы вам действительно нравились компоненты и то, что будет делать каждый логический фрагмент кода. Но, с другой стороны, это отделяет ваши реализации друг от друга, делает его более тестируемым и пригодным для повторного использования. Вы также можете менять компоненты в любое время (во время компиляции или выполнения, если на то пошло), что дает вам некоторую гибкость при создании новых объектов.

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

Также изучите (например, ознакомьтесь с API) движок Unity, который имеет аналогичную модель агрегации и наследования, где интерфейсы являются ключом к абстракции.

Ответ №2:

Обычно вам требуется обычное определение класса, расширяющее movieclip, затем настройте свой герой movieclip на использование этого класса в параметрах экспорта для actionscript. Интерфейс, скорее всего, вообще не нужен для вашей игры.

Ответ №3:

Просто для пояснения — интерфейсы реализованы, а не унаследованы. Поэтому не имеет значения, какой тип класса вы создаете, который реализует iHero. Итак, чтобы создать тип библиотечного класса, который реализует Ihero, расширьте отображаемый объект, такой как Sprite или MovieClip, а затем используйте ключевое слово implements для указания класса, реализующего Ihero.

Добавьте методы Ihero, и теперь у вас есть класс объектов отображения, который реализует iHero. Это может выглядеть примерно так (обратите внимание, что функция конструктора не предоставляется)

 package 
{
    import flash.display.Sprite;
    import com.interfaces.IHero;

    /**
     * ...
     * @author Zachary Foley
     */
    public class MyDisplayObkect extends Sprite implements IHero  
    {

        public function MoveLeft():void
        {
            // Add Implementation here;
        }

        public function MoveRight():void
        {
            // Add Implementation here;
        }

        public function MoveUp():void
        {
            // Add Implementation here;
        }

        public function MoveDown():void
        {
            // Add Implementation here;
        }

        //in battle
        public function DoDamage(isCasting:Boolean):void
        {
            // Add Implementation here;
        }

        public function DoHeal():void
        {
            // Add Implementation here;
        }

        public function Flee():void
        {
            // Add Implementation here;
        }

        public function TakeDamage():void
        {
            // Add Implementation here;
        }
        public function IsAlive():Boolean
        {
            // Add Implementation here;
        }

        public function CheckDeath():void
        {
            // Add Implementation here;
        }

        public function Die():void
        {
            // Add Implementation here;
        }

    }

}