smalltalk超简明教程.docx

上传人:b****6 文档编号:8538992 上传时间:2023-01-31 格式:DOCX 页数:15 大小:25.49KB
下载 相关 举报
smalltalk超简明教程.docx_第1页
第1页 / 共15页
smalltalk超简明教程.docx_第2页
第2页 / 共15页
smalltalk超简明教程.docx_第3页
第3页 / 共15页
smalltalk超简明教程.docx_第4页
第4页 / 共15页
smalltalk超简明教程.docx_第5页
第5页 / 共15页
点击查看更多>>
下载资源
资源描述

smalltalk超简明教程.docx

《smalltalk超简明教程.docx》由会员分享,可在线阅读,更多相关《smalltalk超简明教程.docx(15页珍藏版)》请在冰豆网上搜索。

smalltalk超简明教程.docx

smalltalk超简明教程

Smalltalk超简明教程

Simberson公司的DavidBuck撰写的此文档是为C/C++/C#/Java程序员介绍Smalltalk的,而且已经得到他善意的许可而得以发布。

如果你对正式的培训有兴趣请联系Simberson,咨询Smalltalk培训。

我听说很多Java和C#程序员说他们看不懂Smalltalk代码。

Smalltalk因为只有很少的语法,所以实际上它非常的简单。

Smalltalk的强大之处是它的环境和类库。

本文意图通过代码对比,使Java和C#程序员迅速理解Smalltalk。

CopyrightDavidBuck2005

●临时变量

Smalltalk不需要变量的类型声明。

临时变量通过两个竖线来定义

Java

Smalltalk

inta;

charb;

floatc;

|abc|

 

●赋值

Smalltalk使用:

=赋值

Java

Smalltalk

a=5;

a:

=5

 

●消息

Smalltalk有三种消息

类型

形式

参数

例子

一元运算符

以小写字母开始的字符和数字

0

squared

二元运算符

连接符

1

+

关键字

使用多个冒号终结文字和数字字符

1或者多个

do:

,between:

and:

传输一个或多个参数时,需要使用关键字消息。

每一个参数前面需要添加关键字。

Smalltalk不使用{}和;分割参数。

例子:

Java

Smalltalk

();

(10);

(20,anotherAccount)

(anotherAccount);

myAccountgetBalance

myAccountsetBalance:

10

myAccounttransfer:

20to:

anotherAccount

myAccount=anotherAccount

●运算优先级:

一元运算符(首先运算)

二元运算符(其次运算)

关键字(最后运算)

在同等优先级下,运算是从左到右

Java

Smalltalk

3+5*6

myAccounttransfer:

20to:

anotherAccount

●常量

Smalltalk中整数类型,字符类型,字符串类型,布尔类型,浮点数类型和双精度浮点数类型都是头等类对象。

整数类型是无限精度的,会按需自动增长,而不会溢出(译者注:

跟内存大小有关)。

实际上,Smalltalk中没有char类型,byte类型,short类型,int类型或者long类型的相对应的类型。

它们都是整数类型。

Java

Smalltalk

5

5

01230

8r1230

0x7f

16r7f

<无对应物>

3r21012(你可以选择你想用的基数)

200L

<无对应物>

2e-5

2e-5

2e-5d

2d-5

'h'

$h

'\u03A9'

Charactervalue:

16r3A9

"hello"

'hello'

"can't"

'can''t'

●特定词

Smalltalk中,nil引用一个真实的对象,它是UndefinedObject类的实例。

true是True类的实例,flase是Flase类的实例

Java

Smalltalk

this

self

null

nil

true

true

false

false

super

base(C#)

super

●方法返回

Java

Smalltalk

returnvalue;

^value

●级联

Java

Smalltalk

<无对应物>

myAccount

deposit:

20;

transfer:

20to:

anotherAccount

●注释

Java

Smalltalk

/*comment*/

etTime();

endTime=

newGregorianCalendar().getTime();

}

Reservationclassmethods:

new

^supernewinitialize

Reservationinstancemethod:

initialize

startTime:

=Timestampnow.

endTime:

=Timestampnow

●块

Smalltalk称对象为块,它是包含可执行代码的对象。

Java中最相似的东西是匿名内部类,C#中,跟匿名托管相类似。

执行“块”无需参数,可以向它发送一个value消息

Smalltalk

|block|

block:

=[3+4].

blockvalue"answeris7"

块可以有参数,每一个块参数的声明必须以冒号(:

)开头,以竖线(|)表示参数列表的结束和块代码的开始。

Smalltalk

|block|

block:

=[:

x:

y|x*2+y].

blockvalue:

5value:

3"answeris13"

●语法结束

到此为止,我们已经介绍了Smalltalk所有的语法。

其余的事情属于类库部分。

你是否注意到我们是否忘记了某些事情if-then-else或者while循环Smalltalk只使用块和普通的消息发送。

●控制结构

Smalltalk没有在语言中内置控制结构。

Smalltalk使用向true或者flase对象发生消息作为替代。

Java

Smalltalk

if(tries>5)

return"Toomanytries";

else

return"Tryingagain";

tries>5

ifTrue:

[^'Toomanytries']

ifFalse:

[^'Tryingagain']

注意^表示从方法返回,不只是适用于块。

●循环

Smalltalk使用块做循环。

由于块是对象,所有我们可以先他们发生消息

Java

Smalltalk

inttries=0;

while(tries<=5){

tryAgain();

tries++;

}

|tries|

tries:

=0.

[tries<=5]whileTrue:

[

selftryAgain.

tries:

=tries+1]

alternatively:

5timesRepeat:

[selftryAgain]

注意timesRepeat:

是整数类型能理解的消息。

它简化了块执行的次数

smalltalk入门

原文标题:

ICanReadC++andJavaButICan’tReadSmalltalk

原文作者:

WilfLaLonde

原文链接:

简介

有很多人告诉我他很熟悉C++或Java,但是却完全读不懂Smalltalk的代码。

对于他们来说,Smalltalk简直无法理解!

对于这个问题我考虑了很久然后得到的结论是他们是对的。

如果我随便挑出一些自己多年以前写的Smalltalk代码,然后假设我只明白Java去阅读的时候,我确信我是无法理解那些代码的。

其实要读懂Smalltalk只须了解一些非常简单的概念,当然有些概念也是比较微妙。

如果“Johnny读不懂Smalltalk代码”,我有办法。

我的办法就是通过实际的例子来帮助新手快速理解Smalltalk的概念。

我假设读者了解什么是面向对象变成,对于那些已经掌握Smalltalk的读者也请先假装一会没有学过smalltalk。

如此简单的文法

有些语法是很容易理解的,例如使用双引号来标识注视块;单引号标示字符串,单个字符前面加$(例如:

$x标示字符“x”)。

除此之外,还有symbol的概念,这是一个特殊的字符串,在整个内存中是唯一的。

当源代码被编译的时候,编译器会搜索整个内存,如果发现相同的symbol存在则使用已存在的那个。

有理数并不节省内存,但是相对于symbol而言处理速度更快(稍候解释)。

“thisisacomment”

‘thisisastring’

#’thisisasymbol’

#thisIsASymbolToo

对于赋值操作和等于号,差别不是很大。

:

=^result

在执行的时候,t和self,a和angle,v和vector有一对一的映射关系。

需要注意的是^表示返回,相当于return关键字。

变量self则相当于this。

如果方法的最后没有显式的返回表达式,则却省为^self。

也就是说,不写return语句也不会有什么问题。

这同时也意味着无论调用者是否需要,类方法都将返回一个对象的引用。

事实上,Smalltalk的语法要求self不能出现在函数名的最前面,如下所示:

rotateBy:

anglearound:

vector

|result|

result:

=COMPUTEANSWER.

^result

Smalltalk的这种关键字语法的优点就是,针对不同的方法可以使用不同的关键字。

例如,我们可以像下面这样定义第二个函数:

trotateAround:

vectorby:

angle

没有必要刻意的去记住参数的顺序,因为关键字暗示了他们的顺序。

当然,作为编程者也有可能滥用关键字。

例如,如果我们像下面这样定义关键字:

trotate:

angleand:

vector

很明显,使用这个函数的人无法通过关键字确定参数的顺序。

这是很不好的编程风格。

如果只有一个参数的话,则无所谓。

但是我们仍然需要只有一个关键字的方法名:

trotateAroundXBy:

angle

trotateAroundYBy:

angle

我更倾向于将关键字理解为一种说明性的参数。

但是如果没有参数的时候该怎么办呢

tmakeIdentity:

collectionadd:

transformation.

哦,你可能会很奇怪这里怎么可能有一个dollars消息,其实这没什么特别的。

为了使这个表达式合法,Integer类中必须有一个dollars方法的定义(100将被当作Integer对象处理)。

虽然在标准的Smalltalk环境中并没有这样的定义,但是我们可以自己添加。

Smalltalk的基类可以简单的通过定义新的继承类来扩展。

因此,句号是表达式的终结符,但是在最后一行表达式后面也可以省略(因此你也可以把句号当成表达式之间的分隔符)。

但是分号也是合法的,他用在层跌消息语法中(往一个对象中一次发送多个对象的语法)。

例如:

|p|

p:

=Clientnew.

pname:

'Jack'.

page:

32.

paddress:

'Earth'.

对于上面这样一个表达式我们应该如下编写:

|p|

p:

=Clientnew.

p

name:

'Jack';

age:

32;

address:

'Earth'.

或者干脆写成:

|p|

p:

=Clientnew

name:

'Jack';

age:

32;

address:

'Earth'.

上面的例子中格式并没太大关系,只要愿意我们甚至可以把所有的句子都写成一行。

很关键的分号指出了前一条消息发送到接受对象并使其状态发生变化之后,下一条消息将被继续发到这个接受对象。

(而不是发到上一条消息的返回值对象,上条消息的返回值将被抛弃或者忽视)。

在最后一个例子当中,new被发送到类来生成一个实例(作为返回值)。

然后“name:

’Jack’”被发送到这个实例。

第一个分号表示“name:

’Jack’”消息返回的结果将被忽略,紧接着“age:

32”被发送到先前的实例。

第二个分号表示“age:

32”返回的结果被忽略,紧接着“address:

’Earth’”被发送到先前的实例。

最后,“address:

’Earth’”返回的结果被保存到变量p。

修改接收者属性的类方法通常都返回接收者自身。

因此变量p就最终被绑定到了被修改了好几次的新生成的类实例对象上。

我们可以将上面的分号替换成“ANDALSO”就会感觉很容易理解这段代码的意思了。

在Smalltalk中类似这样向同一个对象连续发送消息的语法称作层跌消息。

分号也可以在子表达式中使用,例如“p:

=(Clientnewname:

'Jack';age:

32;address:

'Earth')”—注意这里的括号。

Get/Set方法使用与实例变量相同的名称

类似name,age,address这样的类实例变量在Smalltalk中全都属于私有变量。

但是类方法可以提供对这些变量的访问。

在C++中(Java也类似),例如,我们可以定义下面这样的访问类实例变量的方法:

longgetAge(){returnage;}

voidsetAge(longnewAge){age=newAge;}

如果你有好几打的类,并且你使用上面这样的编码约定,你将会发现最终你的代码中有一大堆的以get和set打头的类方法。

当然,如果你碰巧决定通过去掉这些重复的前缀以便让类方法名短些,你会发现C++的编译器将会无法编译,因为他无法从名称区分变量和函数。

但是Java的编译器对于下面这样的代码则没有什么问题。

longage(){returnage;}

voidage(longnewAge){age=newAge;}

你能区分变量age和消息age吗你应该可以。

当你使用这条消息的时候,你需要加上括号,就像“age()或者age(22)”;当你引用这些变量的时候,则不需要使用括号。

同样的类方法在Smalltalk中可以写成下面这样:

age^age

age:

newAgeage:

=newAge

不过,我们通常通过写成两行来让代码更可读:

age

^age

age:

newAge

age:

=newAge

在Smalltalk中没有括号可以帮助你区分变量和消息,但是要区分也不是很难。

如果你行的话,应该可以看出下面这句话中哪些是变量,哪些是方法:

ageageage:

ageage+ageage

好吧,答案是3;第一个age必然是一个变量,第四个也是(每个关键字后面都必须是一个子表达式;所有的表达式都必须以变量开头),还有第七个(在一个二元操作符后面,也必须是一个子表达式)。

用更简单典型的例子应该更容易理解,如下:

namesizeArraysareconceptuallyorderedcollectionsthatcan’tchangesize.

|ab|

a:

=OrderedCollectionnew

add:

#red;

add:

#green;

yourself.

b:

=Dictionarynew

at:

#redput:

#rouge;

at:

#greenput:

#vert;

yourself.

Ineachoftheaboveassignments,thevariableisboundtotheresultofthelastmessageexecuted;.,theresultof“yourself”whichis,hopefully,thenewlycreatedcollection.Message“yourself”isdesignedtoreturnthereceiver(almostlikeano-op)but“add:

”and“at:

put:

”donot(theyreturntheirlastparameter).Sowithout“yourself”,wewouldbind“a”to#green”and“b”to#vert.

Ideliberatelyusedcascadingaboveinordertoexplainwhy“yourself”isusedatallsinceitappearsinisolatedmethodsinthebuilt-inclasses.

ThebigadvantagetoSmalltalkcollectionsisthatyoucanputanyobjectswhatsoeverinthecollections.

Eventhekeysindictionariescanbeanytypeofobject.Also,theobjectsinaspecificcollectiondon’thavetobethesametype;theycanallbedifferenttypes.Wedon’tneedtoinventnewkindsofcollectionsjustbecausewewanttoaccumulateinstancesofabrandnewclass.

Orderedcollectionscanbeaccessedlikearrays;.,“aat:

1”indexedstartingat1.Dictionariesareaccessedthesamewaytoo;.,“bat:

#red”.Buttherearemanyapplicationswherewedon’tneedtodealwiththekeys.Forthese,thereareverysimplyloopingfacilitiesthatiteratethroughtheitems;.,

ado:

[:

item|

USEitemFORSOMETHING].

bdo:

[:

item|

USEitemFORSOMETHING].

Loopvariable“item”getstheelementsofthecollectionone-by-oneeveniftheyarealldifferenttypes.

Ifnecessary,wecaneasilyfindoutwhatsomethingisatexecutiontime;.,“itemisKindOf:

Boat”returnstrueorfalse.Therearealsomanyspecial-casequerymessageslike“itemisCollection”or“itemisNumber”.Therearealsomanyloopingconstructsthatcreateandreturnnewcollectionssuchas

c:

=clientsselect:

[:

client|clientnetWorth>500000].

d:

=clientscollect:

[:

client|clientname].

Inthefirstcase,wegetasubcollectionofthoseclientsthatareprettyrich.Inthesecond,wegetacollectionofnames(theoriginalcollectionwasacollectionofclients).

序列化抽象无须创建新的class

Everynowandthen,areaderwillfindcodethatlookslike

stuffvalue:

xvalue:

yvalue:

z

wherethekeywordsareall“value:

”.Thisclearlylooksuselessandbewilderingtoanon-Smalltalkreader.Whatishappeningisthattheprogrammerhas(typically)createdanewabstractionfacility.

LetmeexplainthisfundamentalcapabilitythatonlySmalltalksupportswithachallenge.GiventhatwehavealreadyintroducedtheClientclassearlier,supposethatwewantasimplefacilityforloopingthroughanindividualclient’sparts;.,wewantthelooptofirstgiveusthename,thenthenexttimearound,wewanttheage,andfinallywewanttheaddress.

TheconventionalsolutioninC++andJavaistocreateaspecialstreamclassorenumerator,saycalledClientIterator,withfacilitiestoinitializeit,toaskitifitisattheend,and,ifnot,toaskforthenextobjectintheiterator.Thenwecanhavealoopthatsetsuptheiteratorand,whilenotattheend,getsthenextobjectandprocessesit.Theadvantageoftheiteratoristhatitcanprovideitsownvariablesforkeepingtrackofwhereit’satinthesequencingprocess;.,it’snotnecessarytoextendtheClientclasswith“temporary”instancevariablesneededforiterating.

Anexamplepieceofcodethatmightmakeuseof

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 工学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1