Smalltalk超~简明教学教材.doc

上传人:小** 文档编号:2081582 上传时间:2019-04-18 格式:DOC 页数:16 大小:45.82KB
下载 相关 举报
Smalltalk超~简明教学教材.doc_第1页
第1页 / 共16页
Smalltalk超~简明教学教材.doc_第2页
第2页 / 共16页
Smalltalk超~简明教学教材.doc_第3页
第3页 / 共16页
Smalltalk超~简明教学教材.doc_第4页
第4页 / 共16页
Smalltalk超~简明教学教材.doc_第5页
第5页 / 共16页
点击查看更多>>
资源描述

1、#*Smalltalk 超简明教程Simberson 公司的 David Buck 撰写的此文档是为 C/C+/C#/Java 程序员介绍 Smalltalk 的,而且已经得到他善意的许可而得以发布。如果你对正式的培训有兴趣请联系 Simberson,咨询Smalltalk 培训。我听说很多 Java 和 C#程序员说他们看不懂 Smalltalk 代码。Smalltalk 因为只有很少的语法,所以实际上它非常的简单。Smalltalk 的强大之处是它的环境和类库。本文意图通过代码对比,使 Java 和 C#程序员迅速理解 Smalltalk。Copyright David Buck 2005

2、 临时变量Smalltalk 不需要变量的类型声明。临时变量通过两个竖线来定义Java Smalltalkint a;char b;float c;| a b c | 赋值Smalltalk 使用 := 赋值Java Smalltalka = 5; a := 5 消息Smalltalk 有三种消息类型 形式 参数 例子一元运算符 以小写字母开始的字符和数字 0 squared二元运算符 连接符 1 +关键字 使用多个冒号终结文字和数字字符 1 或者多个 do:,between: and:传输一个或多个参数时,需要使用关键字消息。每一个参数前面需要添加关键字。Smalltalk 不使用和;分割参

3、数。例子:Java SmalltalkmyAccount.getBalance();myAccount.setBalance (10);myAccount.transfer(20,anotherAccount)myAccount.equals (anotherAccount);myAccount getBalancemyAccount setBalance: 10myAccount transfer: 20 to:anotherAccountmyAccount = anotherAccount#* 运算优先级:一元运算符 (首先运算)二元运算符 (其次运算)关键字 (最后运算)在同等优先级下,

4、运算是从左到右Java Smalltalk3 + 5 * 6 /答案是 33 3 + 5 * 6 “答案是:48”注意 Smalltalk 版本,这个表达式实际上是两个消息:消息 1接受者:3消息: +参数:5结果: 8消息 2接受者: 8消息: *参数: 6结果:48 语句Smalltalk 使用句号分割语句。最后一条语句不需句号。Java SmalltalkmyAccount.deposit(20);myAccount.transfer(20,anotherAccount);myAccount deposit: 20.myAccount transfer: 20 to:anotherAcc

5、ount 常量Smalltalk 中整数类型,字符类型,字符串类型,布尔类型,浮点数类型和双精度浮点数类型都是头等类对象。整数类型是无限精度的,会按需自动增长,而不会溢出(译者注:跟内存大小有关) 。实际上,Smalltalk 中没有 char 类型,byte 类型,short 类型,int 类型或者 long 类型的相对应的类型。它们都是整数类型。Java Smalltalk5 501230 8r12300x7f 16r7f3r21012 (你可以选择你想用的基数)200L 2e-5 2e-52e-5d 2d-5h $hu03A9 Character value: 16r3A9“hello“

6、 hello“cant“ cant#* 特定词Smalltalk 中,nil 引用一个真实的对象,它是 UndefinedObject 类的实例。true 是 True 类的实例,flase 是 Flase 类的实例Java Smalltalkthis selfnull niltrue truefalse falsesuperbase (C#)super 方法返回Java Smalltalkreturn value; value 级联Java SmalltalkmyAccountdeposit: 20;transfer: 20 to: anotherAccount 注释Java Smallta

7、lk/* comment */ another comment“comment“ 实例创建Smalltalk 中,类是真实的对象。创建实例,只需向 class 发送 new。针对类的方法称为类方法(类似于 Java 的 static methods) 。Java Smalltalknew Reservation(); Reservation new 构造函数Smalltalk 没有构造函数。如果你想执行实例初始化,你可以重定义“new”类方法来初始化实例。Java SmalltalkReservation()startTime = new GregorianCalendar().getTime

8、();endTime = new GregorianCalendar().getTime();Reservation class methods:newsuper new initializeReservation instance method:initializestartTime := Timestamp now.endTime := Timestamp now #* 块Smalltalk 称对象为块,它是包含可执行代码的对象。Java 中最相似的东西是匿名内部类,C# 2.0中,跟匿名托管相类似。执行“ 块” 无需参数,可以向它发送一个 value 消息Smalltalk| block

9、 |block := 3 + 4.block value “answer is 7“块可以有参数,每一个块参数的声明必须以冒号(:)开头,以竖线(|)表示参数列表的结束和块代码的开始。Smalltalk| block |block := :x :y | x * 2 + y.block value: 5 value: 3 “answer is 13“ 语法结束到此为止,我们已经介绍了 Smalltalk 所有的语法。其余的事情属于类库部分。你是否注意到我们是否忘记了某些事情?if-then-else 或者 while 循环? Smalltalk 只使用块和普通的消息发送。 控制结构Smallta

10、lk 没有在语言中内置控制结构。Smalltalk 使用向 true 或者 flase 对象发生消息作为替代。Java Smalltalkif (tries 5)return “Too many tries“;elsereturn “Trying again“;tries 5ifTrue: Too many triesifFalse: Trying again注意 表示从方法返回,不只是适用于块。 循环Smalltalk 使用块做循环。由于块是对象,所有我们可以先他们发生消息Java Smalltalkint tries = 0;while (tries rotate(a,v); /For C

11、+t.rotate(a,v); /For Java 上面的代码向对象 t 发送消息(注:就是调用类方法) rotate,并指定了参数 a 和 v。为了理解这段代码,读者通常需要继续察看作为参数的变量的申明及其类型。让我们假设其有如下的申明: Transformation t;float a;#*Vector v; #*在 Smalltalk 中,变量可以引用任何对象,因此在申明变量的时候没有必要指定变量的类型。例如:| t a v| 由于没有变量类型申明,好的 Smalltalk 程序员都会使用能暗示变量类型的变量名。因此,上面的申明我们通常如下表示: | aTransformation an

12、gle aVector| 但是后面请允许我继续使用先前的变量名,因为杂志专栏给我可利用的版面很小。让我们进一步消除那些不必要的东西来继续“优化”C+和 Java 的语法。例如,下面的代码应该仍然很好理解: t.rotate(a,v); /原文t rotate(a,v); /有谁需要句点吗? (t 和 rotate 中间的圆点)t rotate a,v; /有谁需要括号吗? 为了进一步改进上面的语法,我们需要知道参数 a 和 v 究竟表示什么。让我们假设整个示例的意思是“围绕端点 v 进行角度为 a 的旋转” 。那么下一步可能如下: t.rotate by a around v; /有谁需要逗号

13、吗? 可是如何才能知道上面这个语句中每个单词的意思呢?我们知道,在这个例子当中,t 是一个变量,rotate 是一个类方法的名称,by 是一个分隔符,a 是一个变量,around 又是一个分隔符,最后的 v 是一个变量。为了消除歧义,我们可以假设如下的变换:在所有的分隔符后面添加一个冒号。那么我们就得到下面的句子: t.rotate by: a around: v; /有谁需要歧义吗? 最终,我们要求所有的分隔符都是方法名称的一部分。也就是说,我们需要的方法的名称是“rotate by: around:”,最后让我们去掉空格,就成了“rotateby:around:” 。我们最好将中间的单词开

14、头大写,于是“rotateBy:around:” ,因此我们的例子就变成了: t.rotateBy: a around: v; /这就是 Smalltalk 也就是说方法名被分成了好几个部分。幸运的是将这些分开的部分想象成一个整体的名字并不困难。当一个类方法被定义的时候,我们可能会写成下面这样: self rotateBy: angle around: vector|result|result := COMPUTE ANWSER.result 在执行的时候,t 和 self,a 和 angle,v 和 vector 有一对一的映射关系。需要注意的是 表示返回,相当于 return 关键字。变量

15、 self 则相当于 this。如果方法的最后没有显式的返回表达式,则却省为self。也就是说,不写 return 语句也不会有什么问题。这同时也意味着无论调用者是否需要,类方法都将返回一个对象的引用。事实上,Smalltalk 的语法要求 self 不能出现在函数名的最前面,如下所示: rotateBy: angle around: vector|result|result:= COMPUTE ANSWER.result Smalltalk 的这种关键字语法的优点就是,针对不同的方法可以使用不同的关键字。例如,我们可以像下面这样定义第二个函数: t rotateAround: vector

16、by: angle 没有必要刻意的去记住参数的顺序,因为关键字暗示了他们的顺序。当然,作为编程者也有可能滥用关键字。例如,如果我们像下面这样定义关键字: t rotate: angle and: vector 很明显,使用这个函数的人无法通过关键字确定参数的顺序。这是很不好的编程风格。如果只有一个参数的话,则无所谓。但是我们仍然需要只有一个关键字的方法名: #*t rotateAroundXBy: anglet rotateAroundYBy: angle我更倾向于将关键字理解为一种说明性的参数。但是如果没有参数的时候该怎么办呢? t makeIdentity: /Can a colon at

17、 the end make sense? 如果关键字是说明性参数,而实际的参数却没有的话,那么我们就不是用关键字。因此一个没有关键字的消息(类方法)将写成下面这样: t makeIdentity /This is Smalltalk 当然,二元操作符(也是类方法,类似 C+语言的 operator)的定义中也可以使用关键字,但是一元操作符不用(上面的 makeIdentity 是一元消息,不是一元操作符) 。当很多消息同时使用的时候,我们可能得到下面这样一个表达式: a negative | (b between: c and: d)ifTrue: a := c negated 作为读者,我相

18、信你现在知道消息 negative 被发送到对象 a(无参数) ,然后 true 或者 false 将被返回;between: c and: d 被发送到对象 b,并返回 true 或者 false。然后对这两个返回结果进行或运算,得到的结果对象被作为 ifTrue:a:= c negated消息的接受者。这是一个 if-then 条件表达式,但是并不像 C+或者 Java 那样需要使用特别的语法。在 Smalltalk 中,这跟其他的类方法调用的语法没有任何差别,只不过消息的接收者是一个布尔对象,而消息的关键字是 ifTrue,参数是a:= c negated(这实际上是一个 block 对

19、象) 。在 Smalltalk 中你将不会看到 a:= -c 这样的表达式,因为没有-这样的一元操作符。但是可以写成 5 这样的表达式,但是这里的负号被作为常量定义的组成部分。因此,当你看到诸如“-3.5 negated truncated factorial”这样的表达式时,你应该立即认识到这里没有关键字。因此-3.5 必须作为 negated 消息的接收者;而得到的结果 3.5 则被作为 truncated 消息的接收者;进一步得到的结果 3 将作为 factorial 消息的接收者,最终得到结果 6。当然,这里也存在优先级的问题,通常是从左到右,一次元消息优先级最高,多参数消息的优先级最

20、低。对于编程的人来说这很重要,但是对于读者来说这并不影响其阅读和理解。哦,对了从左到右的优先级实际上意味着: 1+2*3 等于 9 操作符之间没有优先级之分。当然你也可能会看到下面这样的表达式,那是因为编写者知道不这样写可能会给不太熟悉 Smalltalk 的阅读者造成困扰: (1+2)*3 尽管这里的括号并不必要。分号与句号的不同 大多数的非 Smalltalk 读者可能会认为分号是表达式的终结符,但在 Smalltalk 中使用的是句号。因此我们不会写下面这样的表达式: account deposit: 100 dollars;collection add: transformation;

21、 正确的写法应该是下面这样: account deposit: 100 dollars.collection add: transformation. 哦,你可能会很奇怪这里怎么可能有一个 dollars 消息,其实这没什么特别的。为了使这个表达式合法,Integer 类中必须有一个 dollars 方法的定义(100 将被当作 Integer 对象处理) 。虽然在标准的Smalltalk 环境中并没有这样的定义,但是我们可以自己添加。Smalltalk 的基类可以简单的通过定义新的继承类来扩展。#*因此,句号是表达式的终结符,但是在最后一行表达式后面也可以省略(因此你也可以把句号当成表达式之

22、间的分隔符) 。但是分号也是合法的,他用在层跌消息语法中(往一个对象中一次发送多个对象的语法) 。#*例如: | p |p := Client new.p name: Jack.p age: 32.p address: Earth. 对于上面这样一个表达式我们应该如下编写: | p |p := Client new.pname: Jack;age: 32;address: Earth. 或者干脆写成: | p |p := Client newname: Jack;age: 32;address: Earth. 上面的例子中格式并没太大关系,只要愿意我们甚至可以把所有的句子都写成一行。很关键的分

23、号指出了前一条消息发送到接受对象并使其状态发生变化之后,下一条消息将被继续发到这个接受对象。(而不是发到上一条消息的返回值对象,上条消息的返回值将被抛弃或者忽视) 。在最后一个例子当中,new 被发送到类来生成一个实例(作为返回值) 。然后“name:Jack ”被发送到这个实例。第一个分号表示“name:Jack ”消息返回的结果将被忽略,紧接着“age:32”被发送到先前的实例。第二个分号表示“age:32”返回的结果被忽略,紧接着“address:Earth ”被发送到先前的实例。最后, “address:Earth”返回的结果被保存到变量 p。修改接收者属性的类方法通常都返回接收者自身

24、。因此变量 p 就最终被绑定到了被修改了好几次的新生成的类实例对象上。我们可以将上面的分号替换成“AND ALSO”就会感觉很容易理解这段代码的意思了。在 Smalltalk中类似这样向同一个对象连续发送消息的语法称作层跌消息。分号也可以在子表达式中使用,例如“p := (Client new name: Jack; age: 32; address: Earth)”注意这里的括号。Get/Set 方法使用与实例变量相同的名称 类似 name,age,address 这样的类实例变量在 Smalltalk 中全都属于私有变量。但是类方法可以提供对这些变量的访问。在 C+中(Java 也类似)

25、,例如,我们可以定义下面这样的访问类实例变量的方法:long getAge () return age;void setAge (long newAge) age = newAge; 如果你有好几打的类,并且你使用上面这样的编码约定,你将会发现最终你的代码中有一大堆的以get 和 set 打头的类方法。当然,如果你碰巧决定通过去掉这些重复的前缀以便让类方法名短些,你会发现 C+的编译器将会无法编译,因为他无法从名称区分变量和函数。但是 Java 的编译器对于下面这样的代码则没有什么问题。 long age () return age;void age (long newAge) age = newAge; 你能区分变量 age 和消息 age 吗?你应该可以。当你使用这条消息的时候,你需要加上括号,就像“age()或者 age(22)”;当你引用这些变量的时候,则不需要使用括号。同样的类方法在 Smalltalk 中可以写成下面这样:

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 实用文档资料库 > 策划方案

Copyright © 2018-2021 Wenke99.com All rights reserved

工信部备案号浙ICP备20026746号-2  

公安局备案号:浙公网安备33038302330469号

本站为C2C交文档易平台,即用户上传的文档直接卖给下载用户,本站只是网络服务中间平台,所有原创文档下载所得归上传人所有,若您发现上传作品侵犯了您的权利,请立刻联系网站客服并提供证据,平台将在3个工作日内予以改正。