Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
209 lines (153 sloc) 4.94 KB

练习13. 再来聊聊原型、对象和方法

在练习8和练习9里,我们分别聊了原型和对象,这里要再做一次练习,巩固一下,当然难度也会加大,继续辛苦打字输入吧,创建一个叫做 ex13.io 的文件,开始吧

// 对象、原型、方法

// 对象
Dog := Object clone
    Dog name := "Hello" // 属性
    Dog sit := method("I'm sitting\n" print) // 对象的方法

Dog name println
Dog sit
Dog slotSummary println

write("\n")

// 对象另一种方式
Person := Object clone do(
	name := "Person"
	walk := method("I'm walking\n" print)
)

Person name println
Person walk
Person slotSummary println

write("\n")

// 继承
Jack := Person clone
    Jack walk
    Jack walk := method("I'm walking and laughing" println) // 重新定义方法
Jack walk
Jack protos println
Jack slotSummary println

write("\n")

// 增加对象的方法?不是
Happy := Dog clone
    Happy name := "Happy"
    Happy name println
    Happy sit
    Happy walk := Jack walk // 这里只是调用了Jack的walk方法的结果
    Happy walk
Happy slotSummary println

有挺多新内容的,慢慢说

检查对象

你可以获得一个对象的槽 (slot) 的列表,方便起见,我们在交互模式下操作:

Io> someObject := Object clone
Io> someObject slotNames

如果要排序显示出来:

Io> someObject slotNames sort

要以漂亮的格式来展示,slotSummary 方法很便捷:

Io> slotSummary
==>  Object_0x7fbc7bd184c0:
  Lobby            = Object_0x7fbc7bd184c0
  Protos           = Object_0x7fbc7bd183e0
  _                = Object_0x7fbc7bd00110
  exit             = method(...)
  forward          = method(...)
  set_             = method(...)

更进一步查看:

Io> Protos
==>  Object_0x7fbc7bd183e0:
  Addons           = Object_0x7fbc7bd18990
  Core             = Object_0x7fbc7bd18450

Io> Protos Addons
==>  Object_0x7fbc7bd18990:
  ReadLine         = Object_0x7fbc7d166580

看起来只有 ReadLine 在插件里面,没有别的了。

查看一个方法,会打印出没有编译的方法代码,我是在macOS中用brew安装的io语言,所以路径长一点:

Io> Lobby getSlot("forward")
==> # /tmp/io-20170923-88856-7x7i5v/io-2017.09.06/libs/iovm/io/Z_Importer.io:148
method(
    Importer import(call)
)

继承

继承

对象收到消息的时候,如果消息符合该对象的某一个槽,就执行,如果找不到,那么就一层一层向上找它的原型. 查找循环会被检测到,它是不被允许的.。如果匹配的槽包含一个可激活的对象,比如Block或者CFunction,它包含任何其他值类型,就会被递归调用. Io命名空间中没有全局变量,根对象被称为Lobby。

因为没有类,只有原型,那么子类和实例本身也就没有任何区别了。这里有一个创建相同子类的例子:

Io> Dog := Object clone
==> Object_0x4a7c0

以上代码设置了Lobby的槽 Dog 为 Object 对象,这个新对象的原型列表只包含一个对 Object 的引用,本质上指明了这就是Object的子类. 实例变量和方法继承自这个原型列表. 如果设置了这个槽,创建新槽并不会改变它的原型对象:

Io> Dog color := "red"
Io> Dog
==> Object_0x4a7c0:
  color := "red"

多重继承

你可以添加任意数量的原型到对象的原型列表上. 当对象收到一个消息的时候,它会深度搜索原型链寻找匹配。

方法

方法就是一种匿名函数,调用的时候,会创建一个对象存储在本地变量集合里面,并且设置这个对象的原型指针和它自己的槽到相应的消息上面. 这个Object的method()方法可以用来创建对象:

method((2 + 2) print)

对象中使用这个 method 的例子:

Dog := Object clone
Dog bark := method("woof!" print)

以上代码创建了一个 Object 的子类 Dog ,并且添加了 bark 槽,这个槽包含了打印 woof! 的代码块. 调用示例:

Dog bark

默认返回值就是最后一行表达式语句的结果。

参数

方法定义的时候可以带参数:

add := method(a, b, a + b)

总的来说,形式如下:

method(<arg name 0>, <arg name 1>, ..., <do message>)

运行 ex13.io ,应该会看到

> io ex13.io
Hello
I'm sitting
 Dog_0x7fd714869f30:
  name             = "Hello"
  sit              = method(...)
  type             = "Dog"


Person
I'm walking
 Person_0x7fd712d10ce0:
  name             = "Person"
  type             = "Person"
  walk             = method(...)


I'm walking
I'm walking and laughing
list( Person_0x7fd712d10ce0:
  name             = "Person"
  type             = "Person"
  walk             = method(...)
)
 Jack_0x7fd712da1a30:
  type             = "Jack"
  walk             = method(...)


Happy
I'm sitting
I'm walking and laughing
 Happy_0x7fd7148468a0:
  name             = "Happy"
  type             = "Happy"
  walk             = "I'm walking and laughing"