14 9月, 2016

变量和属性

内容纲要

变量的概念

所谓变量(Variable)就是一个拥有名称(标识符)的数据,并且这个数据是可以通过它的名称被引用或者是修改的。 使用变量的好处是增强程序的可读性、可拓展性等等。
在AppleScript中使用下面语句来声明一个变量:

set name to value as type    --as type 可省略

其中: name为变量名称;
      value为其初始值;
      as type(可省)用来强制指定类型;
      此外,很多命令本身带有返回值,因此类似下面这样的语句也是有意义的,并且非常有用。

set myResult to the result of (make new folder at desktop)   --需要tell app "Finder"

其中: myResult为自定义的名称;
      the result of 语句用于获得命令的结果。
      **注意:并不是所有命令都有返回结果。**

全局变量和局部变量

说到全局变量(Global Variables)和 局部变量(Local Variables),不得不再次提到面向对象的一些概念。 用最简单的话来说:

  • 局部变量: 只在一个对象内部有效(可访问和修改),在其他对象里没法访问。
  • 全局变量: 只要在同一个脚本(脚本包)内,任何对象都鞥访问(和/或修改)的。
  • 在不指定全局和局部时,变量默认都为局部变量。

通过时间处理器和脚本对象来理解
下面简单介绍AppleScript中的两个新内容---事件处理器(Handler)和 脚本对象(Script Object)。

  • 事件处理器: 相当于其他语言中的方法或者函数。 它可以拥有形式参数。
    以“on handlerName”开始,以“end handlerName”结束。
  • 脚本对象:一个脚本中的子脚本(或者说是子空间)。
    以“script name”开始,以“end script”结束。

现在我们可以进一步把局部变量的含义具体化:局部变量的生存空间仅仅在一个事件处理器或脚本内,一旦离开这两个对象,局部变量将无法被访问。对于事件处理器来说,传入的参数(即“形式参数”)是最典型的局部变量。

我们来看这个较为复杂的例子,包含了脚本对象、事件处理器和变量重载。

set message to "最先定义的"                --定义局部变量message
run aNewScript                          --运行脚本对象
displayA("作为形式参数定义的")             --激活事件处理器displayA,并传递参数
---------------------------------
--脚本对象定义开始--
script aNewScript                       --aNewScript是脚本对象的名称
    set message to "在脚本对象里定义的"    --重定义局部变量message(重载)
    display dialog message              --显示一个包含内容message的对话框
end script
--脚本对象定义结束--

--事件处理器定义开始--
on displayA(message)                    --displayA是事件处理器的名称;message是形式参数(一个局部变量)
    display dialog message              --显示一个包含内容message的对话框
end displayA
--事件处理器定义结束--

运行后,将依次显示下面两个对话框:
 

强制全局或者局部
在定义变量之前,增加“Global name”(全局)或者“Local name”(局部)语句,可以强制控制变量的生存空间,其中name为变量名称。

数据共享机制

所谓数据共享机制,就是在复制和修改时---尤其是通过语句“set b to a”(把变量b赋值为变量a的值)方式时,AppleScript对于原数据和新数据内容的处理方式。AppleScript的数据处理方式和其他主流编程语言是基本一致的。

基本数据类型的共享机制(不含Record和List)

对于非Record和List数据,都是采用“拷贝”(pass-by-value,俗称“传值”)。通过实例来说明:

set a to 1                          --给变量a赋值1
set b to a                          --给变量b赋值为a的值
display dialog "赋值的结果:a=" & a & ";b=" & b
                                    --显示a和b的值
set b to 0                          --修改变量b的值为0
display dialog "修改变量b之后:a=" & a & ";b=" & b
                                    --再次显示a和b的值

运行之后,两个对话框分别显示:

赋值的结果:a=1;b=1
修改变量b之后:a=1;b=0

结果证明:对于整数型数据,通过“set b to a”方式进行的赋值,b将得到a中数据的拷贝,而不是共享一个数据。以后修改a和b的值,将互不影响。对于除了Record和List之外的基本数据类型,用得都是这样的“拷贝”方式。

Record和List的数据共享机制

Record和List型数据,如用“set b to a”语句,将采用“共享数据,只增加引用参考(Referencce)”的方式(pass-by-reference,俗称“传引用”或者“传参考”)。

set a to {1,2,3,4,5}                --定义a为List型数据
set b to a                          --给变量b赋值为a的值(List型)
display dialog "赋值的结果:a=" & a & ";b=" & b
                                    --显示a和b的值
set item 1 of b to 0                --修改List b中的第一个值为0
display dialog "修改变量b之后:a=" & a & ";b=" & b
                                    --再次显示a和b的值

运行之后,两个对话框分别显示:

赋值的结果:a=12345;b=12345
修改变量b之后:a=02345;b=02345

结果证明:对于List(包括Record)通过“set b to a”方式实现的是数据共享,而不是拷贝! 实际上a和b指向的是内存中的同一个位置,a和b只是同一内存位置的不同引用!

copy 关键字

如果想要List和Record数据交换方式和其他数据一样,那么需要将“set”改为“copy”,需要注意:copy和set中的源数据和目标数据的位置是相反的,并且copy的目标数据必须要事先定义。

set a to {1,2,3,4,5}                --定义a为List型数据
set b to 1                          --需要提醒的是,使用copy之前必须先定义
copy a to b                         --将a的值赋给变量b(List型)
display dialog "赋值的结果:a=" & a & ";b=" & b
                                    --显示a和b的值
set item 1 of b to 0                --修改List b中的第一个值为0
display dialog "修改变量b之后:a=" & a & ";b=" & b
                                    --再次显示a和b的值

运行之后,两个对话框分别显示:

赋值的结果:a=12345;b=12345
修改变量b之后:a=12345;b=02345

属性

属性(Property)是一个非常熟悉的名字。比如文件的名称、大小、修改时间、类型都是属性。属性是用来描述对象的。在AppleScript中可以自己定义属性,它的用途就好像变量一样(当然它和变量是有区别的)。
定义属性的语句如下:

property Label : value  

其中:   Label为属性的标签(相当于变量的名称)
        value为属性值
请注意: 这个语句不是用来赋值的,而是用来初始化一个属性的!

属性的引用和修改方法和变量是一致的,比如set用来赋值。

属性和变量的区别

属性和变量的根本区别在于其稳固性(Consistence)。所谓稳固性,即脚本退出后,其值是否保持不变。属性在脚本退出运行后,仍然记录下它最后的值,并且下一次运行时可以被调出。 因此,属性的一个用途就是:记录一个脚本运行了多少次,代码如下:

property countTimes : 0
set countTimes to countTimes + 1
display dialog "这是第" & countTimes & "次运行此脚本。"

不断运行这个脚本(不要重新编译),会得到一个对话框精确地说明这是第几次运行。 如果将countTimes定义为变量,那么将无法实现功能。
属性的另一个特点是没有全局和局部之分,所有属性都是全局的。

预定义变量

有些变量是预定义的,它包含预设值(常数)或者可以实现特殊功能。以下是几个常用的预定义变量:

  • result: 记录最近一个命令执行的结果,如果命令没有结果,那么将会得到错误
  • it: 指代最近的一个tell对象
  • me: 这指代码脚本。用法举例 path to me 返回该脚本所在绝对路径
  • tab: 用于string,一个制表符
  • return: 用于string,一个换行符

You may also like...

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注