OTCL用户手册
OTCL用戶手冊
本手冊主要目標為幫助你快速上手OTCL,我們假設(shè)你已經(jīng)熟悉面向?qū)ο缶幊痰母拍?/span>.
?
和C++的比較
對于C++的程序員來說,他們可能對OTCL里面的面向?qū)ο缶幊谈拍畈惶晳T.其中的差別如下:
1,和C++中只能存在單個類定義來比較,OTCL可以有多個定義.每個成員函數(shù)的定義(用關(guān)鍵詞instproc)都給類增加一個方法.每個變量的定義(用關(guān)鍵詞set或函數(shù)體內(nèi)使用instvar)都給對象增加一個變量.
2,和C++中的構(gòu)造函數(shù)不同,OTCL使用一個叫做init的instproc.相對于C++中的析構(gòu)函數(shù),otcl使用一個名字為destroy的instproc.而且OTCL里的構(gòu)造函數(shù)和析構(gòu)函數(shù)并不自動和基類結(jié)合,需要用next顯式調(diào)用.
3,和C++不同的是OTCL方法往往通過對象進行調(diào)用(???).函數(shù)體內(nèi)的關(guān)鍵詞self相當于C++中的this指針.而且,OTCL方法常常是虛擬函數(shù)(virtual)
4,與C++中調(diào)用被繼承的方法不同,OTCL通過施用next來調(diào)用.next將通過查找繼承關(guān)系來找到被繼承的方法和變量.
5,避免在OTCL中施用static方法和變量,因為OTCL中沒有對應(yīng)的關(guān)鍵詞.請通過在類對象內(nèi)部共享變量,并且通過使用關(guān)鍵詞class來訪問.這種行為會被繼承.如果一個不需要被繼承的話,使用proc而非instproc關(guān)鍵詞.
?
OTCL編程
假設(shè)我們在程序中需要使用大量的面包,我們可以構(gòu)造一個面包類
% Class Bagel
Bagel
第一行定義一個面包的類,%為提示符,第二行為第一行語句的輸出,即類名
我們還可以通過info方法來跟蹤類,比如:
% Bagel abagel
abagel
% abagel info class
Bagel??????//顯示該變量的類名
% Bagel info instances
abagel????//顯示該類的繼承關(guān)系
當然,現(xiàn)在的面包類不能做太多的事情,首先,它應(yīng)該記錄自己是否已經(jīng)被烤過.所以我們通過關(guān)鍵詞set來創(chuàng)建一個變量記錄這個狀態(tài).在類里面所由的變量,都有著C++中的public屬性,同樣,info方法可以幫助我們跟蹤類.
% abagel set?toasted 0
0
% abagel info vars//跟蹤類中的變量
toasted
% abagel set?toasted
0
然而,對于面包來說,剛開始做出的面包都是未曾烤熟的,所以我們需要加入一個init的構(gòu)造函數(shù)來實現(xiàn)它.一般來說,如果你需要新創(chuàng)建的變量能被初始化,你需要實現(xiàn)這個init函數(shù)
% Bagel instproc init {args} {
?$self? set? toasted 0?
?eval $self? next $args
}
% Bagel bagel2
bagel2
% bagel2 info vars
toasted
% bagel2 set?toasted
0
這里有許多細節(jié)值得探討.作為創(chuàng)建對象的一部分,系統(tǒng)在對象被分配后將立刻調(diào)用init.在上面的代碼中,initproc方法給類Bagel增加了一個叫做init的方法,所以系統(tǒng)將在新的Bagel對象創(chuàng)建時找到它并調(diào)用它.
在init函數(shù)內(nèi)部,同樣有一些細節(jié)問題.調(diào)用next方法是init函數(shù)的常有動作,我們將在后面討論它.其中self變量包含程序運行時對象的名字,在上一段代碼中就將代表bage2,它相當于C++中的this指針.這里還有兩個關(guān)鍵詞你可能會感興趣,proc和class,其中proc關(guān)鍵詞用來定義成員函數(shù),但該函數(shù)不能被子類繼承.
?
現(xiàn)在我們的面包類能夠表示它是否已經(jīng)進過烘烤房,除了在最前面尚未定義init方法的時候定義的那個面包abagel,所以我們首先將它銷毀,然后重新開始:
% Bagel info instances
bagel2 abagel
% abagel destroy
% Bagel info instances
bagel2
% Bagel abagel
abagel
現(xiàn)在我們可以給面包定義一個方法以便我們能將其送入烘烤房.在這里我們施用關(guān)鍵詞instproc,以便該方法能被子類繼承(所由面包都需要烘烤操作).定義的格式和TCL差不多,都有參數(shù)列表和函數(shù)體.
% Bagel instproc toast {} {
?$self? instvar? toasted
?incr toasted
?if {$toasted>1} then {
???error "something's burning!"
?}
?return {}
}
% Bagel info instprocs//查看能被繼承的方法
init toast
在toast方法中除了設(shè)置toasted變量外,該方法還展示了instvar方法的調(diào)用.該方法用來聲明變量,并將其帶入當前的作用域.因此在前面通過set初始化的變量toasted,能夠在當前的作用域中通過局部變量toasted來操作.
我們可以和使用info和destory相類似的方法來烘烤面包,這也說明在系統(tǒng)函數(shù)和用戶自定義的函數(shù)之間,并煤油什么區(qū)別.
% abagel toast
% abagel toast
something's burning!
現(xiàn)在面包已經(jīng)實現(xiàn)了,但為了外觀的好看,我們還研制出了一種陀螺面包,對此,我們將其作為一個獨立的類來實現(xiàn):
% Class SpreadableBagel -superclass Bagel
SpreadableBagel
% SpreadableBagel?info superclass
Bagel
% SpreadableBagel?info heritage
Bagel Object
在該代碼中,首先定義一個繼承自Bagel類的陀螺面包 SpreadableBagel 類,這通過關(guān)鍵詞superclass來定義,而且通過使用info查看它的繼承關(guān)系可以得知,該類繼承自兩個類,Bagel和Object,奇怪嗎?哪里來的Object?原來在OTCL中,所由的對象都默認繼承自Obejct,所以Bagel直接從Object繼承,然后 SpreadableBagel 再繼承自Bagel.
-superclass還需要更多的解釋.First,you might be wondering why all methods except create are called byusing their name after the object name, as the second argument. Theanswer is that create is called as part of the system's unknownmechanism if no other method can be found. This is done to provide thefamiliar widget-like creation syntax, but you may call createexplicitly if you prefer.
?
Second,as part of object initialization, each pair of arguments is interpretedas a (dash-preceded) procedure name to invoke on the object with acorresponding argument. This initialization functionality is providedby the init instproc on the Object class, and is why the Bagel initinstproc calls next. The following two code snippets are equivalent(except in terms of return value). The shorthand it what you use mostof the time, the longhand explains the operation of the shorthand.
?
???% Class SpreadableBagel
???SpreadableBagel
???% SpreadableBagel superclass Bagel
?
???% Class create SpreadableBagel
???SpreadableBagel
???% SpreadableBagel superclass Bagel
?
???% Class SpreadableBagel -superclass Bagel
???SpreadableBagel
一旦你明白了這個關(guān)系(我沒明白),那么你就能意識到對象的創(chuàng)建沒什么特別的.例如你可以增加其它的選項比如:
???% Bagel instproc size {n} {
?????$self set bites $n
???}
???% SpreadableBagel? abagel -size 12
???abagel
???% abagel set bites
???12
對于SpreadableBagel我們需要增加一些特有的方法和屬性,這樣我們就需要init方法,比如:
% SpreadableBagel instproc init {args} {
?$self? set? toppings {}
?eval $self? next $args
}
% SpreadableBagel instproc spread {args} {
?$self? instvar toppings
?set toppings [concat $toppings $args]
?return $toppings
}
現(xiàn)在init函數(shù)里的next可以解釋清楚了,由于SpreadableBagel同樣也是面包(Bagel ),所以我們也需要設(shè)置SpreadableBagel在剛做出的時候尚未被烘烤,所以我們調(diào)用next來回溯繼承樹使得父類的構(gòu)造函數(shù)也被調(diào)用.
在這個例子里,Bagel類的init函數(shù)將會被調(diào)用,eval是用來整理參數(shù)序列中的參數(shù).同樣,當Bagel類中的init被調(diào)用的時候,還將調(diào)用Object類的init函數(shù).
?
現(xiàn)在讓我們給面包類增加一個品嘗動作:
% Bagel instproc taste {} {
?$self instvar toasted
?if {$toasted == 0} then {
???return raw!
?} elseif {$toasted == 1} then {
???return toasty
?} else {
???return burnt!
?}
}
?
% SpreadableBagel instproc taste {} {
?$self instvar toppings
?set t [$self next]
?foreach i $toppings {
???lappend t $i
?}
?return $t
}
?
% SpreadableBagel abagel
abagel
% abagel toast
% abagel spread jam
jam
% abagel taste
toasty jam
當然,我們還需要給面包加上其它許多的東西,比如洋蔥,罌粟,芝麻等,我們可以通過使用內(nèi)部變量來代表這一切,但這并不是最佳的解決方案.我們可以通過構(gòu)造繼承類來實現(xiàn):
% Class Sesame
Sesame
% Sesame instproc taste {} {
?concat [$self next] "sesame"
}
% Class Onion
Onion
% Onion instproc taste {} {
?concat [$self next] "onion"
}
% Class Poppy
Poppy
% Poppy instproc taste {} {
?concat [$self next] "poppy"
}
這看樣子沒起什么作用,但:
% Class SesameOnionBagel -superclass {Sesame Onion SpreadableBagel}
SesameOnionBagel
% SesameOnionBagel abagel -spread butter
% abagel taste
raw! butter onion sesame
對于多繼承,由系統(tǒng)來決定一個線性的繼承序列,可以通過info方法來顯示,比如:
% SesameOnionBagel info heritage
Sesame Onion SpreadableBagel Bagel Object
next將根據(jù)這個序列來依次調(diào)用.
?
我們還可以把我們的混和類和其它類結(jié)合,比如:
% Class Chips
Chips
% Chips instproc taste {} {
?return "crunchy"
}
% Class OnionChips -superclass {Onion Chips}
OnionChips
% OnionChips abag
abag
% abag taste
crunchy onion
其它參考文獻:
???* There is support for autoloading libraries of classes and methods. See OTcl Autoloading for details.
???*There is a C level interface (as defined by otcl.h) that allows newobjects and classes to be created, and methods implemented in C to beadded to objects. See OTcl C API for details.
???*Classes are special kinds of objects, and have all of the properties ofregular objects. Thus classes are a convenient repository forprocedures and data that are shared by their instances. And thebehavior of classes may be controlled by the standard inheritancemechanisms and the class Class.
???*Methods called procs can be added to individual object, for sole use bythat object. This allows particular objects to be hand-crafted, perhapsstoring their associated procedures and data.
???*User defined methods are treated in the same way as system providedmethods (such as set and info). You can use the standard inheritancemechanisms to provide your own implementation in place of a systemmethod.
·?????????????????????Thereare several other system methods that haven't been described. arraygives information on array instance variables, unset removes instancevariables, there are further info options, and so forth.
?
?
·?????????????????????Objects in Otcl:http://bmrc.berkeley.edu/research/cmt/cmtdoc/otcl/object.html
·?????????????????????Classes in Otcl:http://bmrc.berkeley.edu/research/cmt/cmtdoc/otcl/class.html
·?????????????????????C API:http://bmrc.berkeley.edu/research/cmt/cmtdoc/otcl/capi.html
·?????????????????????OTcl Autoloading :http://bmrc.berkeley.edu/research/cmt/cmtdoc/otcl/autoload.html
總結(jié)
- 上一篇: 1x1px透明GIF的Base64编码
- 下一篇: 为什么通常在发送数据埋点请求的时候使用的