[中级] Func() 和 ObjBindMethod() 的关

作者: d61f25068828 | 来源:发表于2019-01-09 10:56 被阅读0次

    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,先把是狗还是羊提供一下。

    image
    ;示例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程序设计系列文章示例问题的解释

    版权声明:

    该文章版权系“心如止水”所有,欢迎分享、转发,但如需转载,请联系QQ:3404624865,得到许可并标明出处和原链接后方可转载。未经授权,禁止转载。版权所有 ©心如止水 保留一切权利。

    文章版本:

    v1

    AHK版本:1.1.30.00

    心如止水

    相关文章

      网友评论

        本文标题:[中级] Func() 和 ObjBindMethod() 的关

        本文链接:https://www.haomeiwen.com/subject/qiywrqtx.html