Io語(yǔ)言快餐(1) - 一切皆是對(duì)象,消息和槽的語(yǔ)言
Io是一種基于原型的語(yǔ)言。Io語(yǔ)法只不過(guò)是把消息全部串聯(lián)起來(lái),每條消息都會(huì)返回一個(gè)對(duì)象,每條消息也都帶有置于括號(hào)內(nèi)的可選參數(shù)。
在Io中,萬(wàn)事萬(wàn)物皆消息,且每條消息都會(huì)返回另一接收消息的對(duì)象。
Io語(yǔ)言沒(méi)有關(guān)鍵字,有的只是少量在行為上接近于關(guān)鍵字的字符。
Io的官方網(wǎng)站是:http://iolanguage.org/
源代碼地址在:https://github.com/stevedekorte/io
在mac下,可以通過(guò)Homebrew安裝io。
補(bǔ)充一句,為什么要了解Io這樣的語(yǔ)言?如果不是《七周七語(yǔ)言》這樣的書(shū)來(lái)介紹它,估計(jì)很少有人關(guān)注到它吧。其實(shí)目的很簡(jiǎn)單,作為js代碼和js虛擬機(jī)的開(kāi)發(fā)人員,學(xué)習(xí)原型化的語(yǔ)言對(duì)于更深入地理解javascript是有難以估量的幫助的。畢竟javascript和Io同源,在原型化思想上都供鑒了Self語(yǔ)言的思想。
一切皆是消息和槽
Io> "Hello,World" print
Hello,World==> Hello,World
這段代碼的意思是,給"Hello,World"字符串發(fā)送print消息。
Io沒(méi)有類(lèi),可通過(guò)復(fù)制現(xiàn)有對(duì)象創(chuàng)建新對(duì)象,現(xiàn)有對(duì)象就是原型。
可以通過(guò)clone消息創(chuàng)建新對(duì)象:
Io> Circle := Object clone
==> Circle_0x7fac57845db0:
type = "Circle"
在Io里,對(duì)象沒(méi)有屬性,而是槽,通過(guò):=可以對(duì)槽進(jìn)行賦值,例:
Io> Circle x := 0
==> 0
Io> Circle y := 0
==> 0
Io> Circle r := 1
==> 1
:=是如果沒(méi)有這個(gè)槽的話(huà),就創(chuàng)建這個(gè)槽,而=是只賦值。
我們可以發(fā)送print消息,看看Circle對(duì)象現(xiàn)在是什么樣子:
Io> Circle print
Circle_0x7fac57845db0:
r = 1
type = "Circle"
x = 0
y = 0
==> Circle_0x7fac57845db0:
r = 1
type = "Circle"
x = 0
y = 0
通過(guò)將槽名發(fā)給對(duì)象作為消息,可以讀取值,例:
Io> Circle x
==> 0
如果發(fā)給對(duì)象一個(gè)不存在的槽名做為消息,會(huì)得到錯(cuò)誤信息,例:
Io> Circle z = 2
Exception: Slot z not found. Must define slot using := operator before updating.
---------
message 'updateSlot' in 'Command Line' on line 1
繼承
Io語(yǔ)言沒(méi)有類(lèi)的概念。但是,它的對(duì)象有帶有type槽的對(duì)象和不帶type槽的對(duì)象這兩種。
如果一個(gè)對(duì)象的首字母為大寫(xiě),它就默認(rèn)是個(gè)帶slot槽的對(duì)象。反之,如果是小寫(xiě),則其沒(méi)有type槽。
我們舉個(gè)例子,假如我們定義了一個(gè)Circle對(duì)象,想生成不同的圓的實(shí)例,那么就可以用不帶type槽的新對(duì)象。
例:
Io> circle1 := Circle clone
==> Circle_0x7faa55409e70:
Io> circle1 x = 1
==> 1
Io> circle1 y = 1
==> 1
Io> circle1 r = 2.5
==> 2.5
Io> circle1 slotNames
==> list(x, r, y)
但是,我們想在圓的基礎(chǔ)上擴(kuò)充成一個(gè)球的對(duì)象,這個(gè)球?qū)ο罂梢宰鰹楦鞣N大小的球的樣板,我們就可以用大寫(xiě)開(kāi)頭做繼承。
例:
Io> Circle slotNames
==> list(type, x, r, y)
Io> Ball := Circle clone
==> Ball_0x7faa536269a0:
type = "Ball"
Io> Ball z := 0
==> 0
Io> ball1 := Ball clone
==> Ball_0x7faa5358cc30:
Io> ball1 x = 1
==> 1
Io> ball1 y = 1
==> 1
Io> ball1 z = 1
==> 1
Io> ball1 r = 1
==> 1
Io> ball1 slotNames
==> list(x, r, y, z)
ball1對(duì)象中并沒(méi)有定義x, y, z, r槽,它們分別繼承自Ball和Circle對(duì)象。請(qǐng)注意,ball1中我們使用的是"="而不是":=",沒(méi)有定義新槽。
我們可以通過(guò)給對(duì)象發(fā)送type消息來(lái)獲取它的類(lèi)型:
Io> Circle type
==> Circle
Io> Ball type
==> Ball
Io> ball1 type
==> Ball
proto消息用于查詢(xún)一個(gè)對(duì)象的原型是誰(shuí):
Io> ball1 proto
==> Ball_0x7faa536269a0:
type = "Ball"
z = 0
Io> Ball proto
==> Circle_0x7faa53659110:
r = 1
type = "Circle"
x = 0
y = 0
方法
方法是一種特殊的槽而已,也沒(méi)什么特殊的。
比如我們寫(xiě)一個(gè)求圓的面積的方法吧:
Io> Circle area := method(3.14*r*r println)
==> method(
3.14 * r * r println
)
調(diào)用一下:
Io> circle2 := Circle clone
==> Circle_0x7faa53434220:
Io> circle2 area
1
==> 3.1400000000000001
Io> circle2 r = 4
==> 4
Io> circle2 area
4
==> 50.240000000000002
對(duì)象知識(shí)復(fù)習(xí)
在繼續(xù)前進(jìn)之前,我們還需要打磨一下知識(shí)。
首先,我們需要理解Circle_0x7faa53434220這樣的對(duì)象的含義。雖然沒(méi)有明確,但是Circle實(shí)際上是一個(gè)指針,Circle_0x7faa53434220才是真正的對(duì)象。
我們來(lái)做這樣一個(gè)實(shí)驗(yàn),對(duì)Circle進(jìn)行兩次定義,然后分別克隆出它們的子對(duì)象,看看是什么情況:
Io> Circle := Object clone
==> Circle_0x7f984f4992b0:
type = "Circle"
Io>
==> nil
Io> Circle x := 0
==> 0
Io> Circle y := 0
==> 0
Io> Circle r := 1
==> 1
Io>
==> nil
Io> Circle slotNames
==> list(type, x, r, y)
Io> circle1 := Circle clone
==> Circle_0x7f984f457c20:
Io> circle1 type
==> Circle
Io> Circle := Object clone
==> Circle_0x7f9850b2b440:
type = "Circle"
Io> Circle x := 0
==> 0
Io> Circle y := 0
==> 0
Io> Circle r := 1
==> 1
Io> Circle slotNames
==> list(type, x, r, y)
Io> circle2 := Circle clone
==> Circle_0x7f98508b3a10:
Io> circle2 type
==> Circle
看起來(lái)circle1和circle2的type都是Circle。
我們繼續(xù)實(shí)驗(yàn),給Circle增加兩個(gè)槽:
Io> Circle area := method(3.1416*r*r println)
==> method(
3.1416 * r * r println
)
Io> Circle desc := "Circle"
==> Circle
原型對(duì)象變了,circle2自然也獲得了area槽:
我們來(lái)驗(yàn)證一下:
Io> circle2 x = 1
==> 1
Io> circle2 y = 1
==> 1
Io> circle2 r = 10
==> 10
Io> circle2 area
10
==> 314.160000000000025
那么,circle1是不是也可以呢?我們也來(lái)試驗(yàn)一下:
Io> circle1 x = 1
==> 1
Io> circle1 y = 1
==> 1
Io> circle1 r = 10
==> 10
Io> circle1 area
Exception: Circle does not respond to 'area'
---------
Circle area Command Line 1
Circle類(lèi)新增的屬性對(duì)于circle1對(duì)象沒(méi)有影響。
這是為什么?我們通過(guò)proto消息來(lái)看一下吧:
Io> circle1 proto
==> Circle_0x7f984f4992b0:
r = 1
type = "Circle"
x = 0
y = 0
Io> circle2 proto
==> Circle_0x7f9850b2b440:
area = method(...)
desc = "Circle"
r = 1
type = "Circle"
x = 0
y = 0
也就是說(shuō)circle1是以Circle_0x7f984f4992b0對(duì)象為原型克隆出來(lái)的,而circle2是以Circle_0x7f9850b2b440為原型克隆出來(lái)的。
它們的type相同,但是proto不同。
為了避免誤解,我們還是盡量保持proto和type一致吧。
小結(jié)
- Io語(yǔ)言是一種原型式的語(yǔ)言,沒(méi)有類(lèi),一切皆對(duì)象
- 對(duì)象有槽,槽可以是任何對(duì)象,方法也是對(duì)象
- 對(duì)象的操作只有一種,發(fā)送消息,消息的結(jié)果返回一個(gè)對(duì)象
- clone出的對(duì)象可以繼承父對(duì)象的槽
- 大寫(xiě)開(kāi)頭的對(duì)象有type槽,小寫(xiě)開(kāi)頭的對(duì)象沒(méi)有type槽
- type和proto可能是不同的