OOP问题:扩展类,覆盖函数和类似jQuery的语法

时间:2010-12-17 10:03:01

标签: flash actionscript-3 oop design-patterns fluent-interface

我与Flash,actionscript 3有OOP相关的问题。这是一个个人项目,我正在寻找这个问题的设计模式或解决方法,我的目标是学习新东西。

我创建了一个名为Chain的类。我创建了这个util-class,使延迟函数调用变得容易。您可以通过添加延迟(以毫秒为单位)来创建一系列函数。即使按相反的顺序,该链也可以多次执行。该类具有返回自身的功能。这使得有可能有​​这样的jQuery样式语法:

var chain:Chain = new Chain(); 
chain.wait(100).add(myFunction1,300).wait(300).add(myFunction2,100);
// etc..

对于这个例子,我留下了许多函数来证明问题。 Chain类主要用于添加函数和启动/停止链。

public class Chain 
{  
 function wait(delay:int = 0):Chain
 {
   // do stuff
   return this;
 }

 public function add(func:Function, delay:Number = 0):Chain
 {
      list.push( new ChainItem(func, delay) );
      return this;
 }
}

现在,我有另一个名为ChainTween的类。我试图分裂一些东西以保持Chain具有一些核心功能,并让ChainTween做一些动画技巧。我有想法创建一个基于Chain类的小型tweenengine。目前它扩展了Chain。它使用来自Chain类的许多受保护变量,并覆盖Chain的一些核心函数,以在Chain的过程中添加补间函数。

public class ChainTween extends Chain
{  
 function animate(properties:Object = null, duration:Number = 0, easing:Function = null):ChainTween
 {
   // do stuff
   return this;
 }
}

现在问题是:我想保留链接语法,但wait()返回一个Chain实例,而Chain没有动画函数。

var chain:ChainTween = new ChainTween();
chain.wait(100).animate({x:200}, 100).wait(250);

我试图在ChainTween类中覆盖wait()和add()函数,但这会导致不兼容的覆盖。

我可以将chain.wait(100)转换为ChainTween,但是当我链接很多链接时,这非常难看并且没用。现在我不想将任何ChainTween函数添加到Chain(也没有虚函数),并且我想保持对所有函数的完成,因此返回Object也不是一个选项。我试图使用一个接口,但这会产生同样的问题,因为接口的功能应该在实现它的类中实现。

现在我已经考虑过在ChainTween中创建一个Chain实例,但这不允许我覆盖函数,然后我应该将很多属性公开而不是protected,这也不是首选。

这是否可行,是否有人为此提供了很好的解决方案?

6 个答案:

答案 0 :(得分:2)

这个问题很常见。您使用的设计模式称为Fluent Interface,如果您使用Google“流畅的界面继承”,您会发现很多问题和很少的答案。

在C#,Java和C++ is to use templates中解决它的常用方法。但是,我无法告诉如何在AS3中实现相同的功能,我发现this topic可能会对您有所帮助。

答案 1 :(得分:1)

如果您希望通过代码完成列出函数,则必须存在。这排除了任何运行时发现方法。我会添加这样的链:

public function animate(args:Object, time:int):Chain {
    throw new Error("Animate is supported only on ChainTween");
}

在ChainTween中被覆盖。不要以为这是一个很大的延伸。

答案 2 :(得分:1)

遵循Chain类的结构,应该可以(并且以某种方式逻辑)使用add方法来调用animate方法...不知道关于Chain类的更多信息,很难更准确,但是这似乎是可能的......它需要在add方法中添加一个新的参数。

var chain:ChainTween = new ChainTween();
var params:Object = {x:200};
chain.wait(100).add(animate, 300 , params).wait(300);

alxx有一个观点,似乎某些东西必须以某种方式给出,与Javascript不同,AS3是强类型语言,这是你的局限性的原因。如果你需要实现特定于旋转,fadeOut的方法,你可能没有很多可用的解决方案。那些方法将返回一个ChainTween,一个链或一个对象,你要同时解除对象和* ...

不知何故,我仍然认为使用add()(或者您可能为此目的创建的任何其他方法)添加rotate,fadeOut或animate方法更符合Chain的设计。

答案 3 :(得分:0)

您可以尝试返回*而不是Chain,但这会删除代码提示。

答案 4 :(得分:0)

如果我是你,我创建了一个IChain界面,仅描述核心功能(addwait等)

答案 5 :(得分:0)

我会选择已经建议的界面想法。 Wait会返回类似'IChainTween'的东西,它只包含配置ChainTween的方法,还有像'then'这样的函数,它返回原始的链。

package
{
    public interface IChainTween
    {
        function doSomething():IChainTween;
        ...
        function then():IChain;
    }
}

package
{
    public class ChainTween implements IChainTween
    {
        private originalChain:IChain;
        public function ChainTween(IChain chain)
        {
            originalChain = chain;
        }
        ...
        public function doSomething():IChainTween
        {
            return this;
        }
        public function then():IChain
        {
            return originalChain;
        }
    }
}