我没有设计许多在其中一个函数(例如一行)中只有少量差异的类,而是根据构造函数参数更改函数。像这样的东西:
public class SomeClass {
public var toDo : Function;
public SomeClass1( option: Boolean){
if (option){
function function1():void{
// something here;
}
toDo = function1;
} else{
function function2():void{
// something here;
}
toDo = function2;
}
}
}
这是好习惯吗?或者,我可以将它分成一个基类和 2 个子类,但是当它们相差如此之小时,将它们作为具有 2 个不同功能的两个不同的类似乎是一种浪费。或者我可以在函数中存储选项和 if 语句,但是每次运行函数时我都必须检查它,因为它每次都相同。最好的办法是什么?
最佳答案
你的方法本质上没有任何问题——这是一种完全有效的方法——只要你准确地理解你在做什么,以及一些警告是什么。
重复的功能
使用这种方法时,我最大的担忧之一是每次新建此类的实例时,都会创建一个新函数。制作 1000 个实例,你就有 1000 个函数 float 。作为方法,只有一个引用实例在稳定的上下文中执行。
解决此问题的一种可能方法是在构造函数之外使用静态函数定义:
public class SomeClass {
public var toDo:Function;
private static var doIt1:Function = function():void { };
private static var doIt2:Function = function():void { };
public function SomeClass(options:Boolean) {
this.toDo = (option) ? doIt1 : doIt2;
}
}
或者,您可以使用对实例方法的引用而不是函数:
public class SomeClass {
public var toDo:Function;
private function doIt1():void { };
private function doIt2():void { };
public function SomeClass(options:Boolean) {
this.toDo = (option) ? doIt1 : doIt2;
}
}
请参阅下一节以更好地区分这两种方法。
不管怎样,这只会分配一个函数,不管你有多少这个类的实例。
绑定(bind)与未绑定(bind)函数
ActionScript 中的方法和函数之间存在细微差别。虽然相似,但它们的工作方式并不完全相同。一个 bound method是从实例中提取的方法。在执行这些方法时,
this
将始终指向它们来自的实例。考虑以下代码:
public class SomeClass {
private var number:Number;
public function SomeClass(val:Number):void {
number = val;
}
public var doIt:Function;
public var getNumberUnbound:Function = function():Number {
return this.number;
}
public function getNumberBound():Number {
return this.number;
}
}
非常简单的示例,构造函数采用
Number
然后有一个返回该值的方法和一个也返回该值的函数,然后是一个名为 doIt
的公共(public)函数目前未分配。所以首先让我们考虑一下:var instance1:SomeClass = new SomeClass(1);
instance1.getNumberBound(); // 1
instance1.getNumberUnbound(); // 1
这将返回
1
正如我们对这两个电话所期望的那样。但是现在,让我们尝试变得棘手并玩弄 .call()
– 或 .apply()
.var instance1:SomeClass = new SomeClass(1);
var instance2:SomeClass = new SomeClass(2);
instance1.getNumberBound.call(instance2); // 1
instance1.getNumberUnbound.call(instance2); // 2
注意这次我们得到了不同的结果。绑定(bind)调用仍返回
1
因为它仍然坚持 instance1
,其中未绑定(bind)调用返回 2
,因为它是在它认为应该在的任何上下文中执行的。事实上,考虑一下:instance1.getNumberBound.call(null); // 1;
instance1.getNumberUnbound.call(null); // ERROR!
在这种情况下,再次
getNumberBound
仍然在 instance1
的上下文中执行,但是未绑定(bind)函数失败,因为 this
现在等于 null
, 和 null.number
显然没有任何意义。现在让我们变得更奇怪:
var instance1:SomeClass = new SomeClass(1);
var instance2:SomeClass = new SomeClass(2);
instance2.doIt = instance1.getNumberBound;
instance2.doIt(); // 1
instance2.doIt = instance1.getNumberUnbound
instance2.doIt(); // 2
在这里你可以看到无论你尝试做什么来分离
getNumberBound
来自 instance1
,你就是做不到。尽管我们已经把一个方法的引用塞进了 instance2
, 它仍然在 instance1
的范围内执行.这就是我的意思,当我说
this
可能不是您期望的那样。取决于它是绑定(bind)还是未绑定(bind),或者调用者是否使用 .call()
显式更改它或 .apply()
, this
可能与您预期的完全不同。我的本能
我会使用 occam 的 Razor ,它对我来说是存储选项并在一个名为
toDo
的方法中进行切换。 .即使您大量调用此函数,单个条件语句的成本也可以忽略不计,我会等待分析器告诉我在尝试找出解决任何性能问题的更好方法之前花费了太长时间。奇怪的是,您的性能问题将在其他地方。也就是说,当它有意义时,我确实使用了这种模式。事实上,您可以将您的工作人员注入(inject)您的实例,并一起避免这种情况。
public class SomeClass {
public var toDo:Function;
public SomeClass(doIt:Function) {
toDo = doIt;
}
}
了解 ActionScript 中的函数式编程概念可能是一件非常强大的事情,一旦您掌握了窍门。我不会避免它,但我会小心使用它。与大多数强大的东西一样,如果使用不当,可能会非常危险。
继承可能有用,但尽量不要陷入“继承是解决一切的办法”。继承应该只真正尝试建模"is"关系,.组合可能在结构上更好,但也可以为功能方法提出论据。
关于actionscript-3 - 嵌套函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11804812/