共计 2894 个字符,预计需要花费 8 分钟才能阅读完成。
AB013-[中级] Func() 和 ObjBindMethod() 的关系
上一篇文章发出来之后,@zhanglei1371 问我 ” Func 和 ObjBindMethod 的关系 ”。
其实 ” 只要是方法就用 ObjBindMethod,只要是函数就用 Func”,大多数时候都是没问题的。
但是深究下去,他们之间是有区别的。
这是个好问题,顺带我介绍一下 Class 的内容。
Class 和 Object
这个地方学过 ” 面向对象 ” 的,可以跳过,这是给没学过的说的。
情景
面向过程
现在假设你要做一款儿童游戏,你需要模拟出很多小动物,比如狗 / 羊等等。你一开始可能这么搞。
DogSound:=” 汪汪~~”
DogName:=” 狗 ”
DogCalling(){
global
MsgBox,% DogName “:” DogSound
return
}
DogFuncObj:=Func(“DogCalling”)
%DogFuncObj%()
是,今天是没问题了,但是明天老板让你做一只羊,后天老板让你做一只猴子,一只兔子,一只考拉。
所以你就复制 / 粘贴 / 复制 / 粘贴,这么一直不停的堆积代码的办法就叫做 ” 面向过程 ”。
面向对象
由于你做的动物非常多,” 动物 ” 这种东西又很有相似性,还有一个办法就是,你先做一个 ” 动物 ” 模板,之后每增加一个新动物,你就往里面填东西就是了。这个办法更方便,更符合人类的认知规律。
这个模板就叫做 Class,翻译过来就是 ” 类 ”,用现代汉语来说就是 ” 种类 ”。现在我们定义一个 Class。
; 示例 1
Class Animal{
;Field
Sound:=”UnKnowSound”
Name:=”UnKnowName”
__New(aName,aSound){
this.Name:=aName
this.Sound:=aSound
return this
}
Calling(){
MsgBox,% this.Name “:” this.Sound
return
}
}
你可以根据这个模板,批量的生成大量的动物,节省你很多的时间。
但是你要明白的是,动物本身是一个抽象的概念,他只是一个 ” 种类 ”,并不是一个实体,而你要生成的狗就是一个实体,实体 的英文就是 Object。这个 Object 常被翻译为 ” 对象 ”,这种编程的方法也叫做 ” 面向对象的编程吧 ”。
下面我们来生成一只狗和一只羊,他们都属于 Object。
TheDog:=new Animal(“Dog”,” 汪汪~”)
TheSheep:=new Animal(“Sheep”,” 咩咩~”)
现在我们让他们都叫叫,听听声。
TheDog.Calling()
TheSheep.Calling()
Func 和 ObjBindMethod 的关系
问题在于 ” 面向对象 ”
搞清楚这一点了之后,”Func 和 ObjBindMethod 的关系 ” 其实就很容易理解了。
比如,你想获取一个 ” 狗叫 ” 的函数对象,你可能要把它用在 HotKey 命令中。(当然,这种没参数的方法可能简单些,这里就当有参数。)
如果你是面向过程,也就是定义的函数,那么你需要这么做。
; 示例 2
DogSound:=” 汪汪~~”
DogName:=” 狗 ”
DogCalling(){
global
MsgBox,% DogName “:” DogSound
return
}
DogFuncObj:=Func(“DogCalling”)
%DogFuncObj%()
但是,现在你用的是 ” 面向对象 ”,那么你就不能用这种方法。
DogFuncObj:=Func(“Calling”)
%DogFuncObj%()
因为,你只提供 Calling 这个方法名,程序不知道该调用狗的还是羊的,程序默认在函数中搜索,又找不到一个叫做 Calling 的函数,那么就会返回 false。
那么就用 ObjBindMethod,先把是狗还是羊提供一下。
; 示例 3
DogFuncObj2:=ObjBindMethod(TheDog,”Calling”),%DogFuncObj2%()
那么能不能用 Func()+Bind() 完全替代 ObjBindMethod()?
大多情况下可以相互代替
大多数情况是可以的,但也有例外。首先我们看一下示例 1,你会发现一个 this 关键字。
这个 this 是什么意思呢? 因为在你建立 Class 的时候,你并不知道将来是狗还是羊,那么你就用 this 来泛指一切动物对象。
; 示例 4
Calling(){
MsgBox,% this.Name “:” this.Sound
return
}
再看一下这个方法,方法的域是独立的,方法中本没有一个叫做 this 的东西,那么 this 从哪里来?
答案是,this 从参数中来,其实这个方法的本来面貌应该是。只是为了可读性,省略了罢了。
; 示例 5
Calling(this){
MsgBox,% this.Name “:” this.Sound
return
}
所以,Func()+Bind() 可以替代 ObjBindMethod(),方法如下。
; 示例 6
DogFuncObj3:=TheDog.Calling.Bind(TheDog),%DogFuncObj3%()
示例 3 和示例 6 是完全等价的。
特殊情况下不能代替
之所以我们能够这么用,是因为 TheDog.Calling 这个东西是我们自己搞出来的,我们对这个 FuncObj 本身具有访问权限。但是,对于系统自带的 Obj,比如 FileObj,我们是没有这个权限的,在这种情况下,我们就只能用 ObjBindMethod。
; 示例 7
file := FileOpen(“D:test.txt”, “r”)
getLine := ObjBindMethod(file, “ReadLine”)
getLine2 := file.ReadLine.Fucn(file)
MsgBox % %getLine%()
MsgBox % %getLine2%()
第一次 %getLine%() 可以读出文字,第二次 %getLine2%() 就生没辙,因为 file.ReadLine 你没有权限拿到。
这个系列的其他文章
看这里
[中级] AHK 元编程初步:对象协议和__Get() v2
[中级] AHK 元编程实战:用__Call() 魔改默认基对象 v2
End
心如止水是 Java/AHK 持续学习者,欢迎您来和我探讨 Java/AHK 问题 ^_^
GitHub
欢迎您来访问我的 GitHub,在这里您可以看到我的代码分享,关注我的最新动态。
欢迎给 新生的 BeanLib 投稿,每一位贡献者的名字都将被铭记。
更多文章:
[专栏] AHK 程序设计 – 简书 (优先持续更新)
[基础] [GIF 动图] 绕过中文输入法发送文本的 3 种方法
[基础] AHK 函数对象系列 - 绑定函数对象 v3
[基础] AHK 函数对象系列 - 绑定方法对象
[基础] 在 AHK 中实现函数重载的效果
[基础] AHK 函数对象系列 - 对象属性与数据域保护 v2
问题解答:
[问题解答] 示例不能运行吗? – 关于 AHK 程序设计系列文章示例问题的解释
版权声明:
该文章版权系“心如止水”所有,欢迎分享、转发,但如需转载,请联系 QQ:3404624865,得到许可并标明出处和原链接后方可转载。未经授权,禁止转载。版权所有 ©心如止水 保留一切权利。
文章版本:
v1
AHK 版本:1.1.30.00