我与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,这也不是首选。
这是否可行,是否有人为此提供了很好的解决方案?
答案 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
界面,仅描述核心功能(add
,wait
等)
答案 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;
}
}
}