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