执行代码

  • Do it(执行代码) Ctrl + D / Cmd + D,用于执行表达式
  • Print it(打印结果) Ctrl + P / Cmd + P,用于打印表达式结果
  • Inspect it(对象检查器) Ctrl + I / Cmd + I,用于查看对象内部结构

数值类型

1, 2, 100, 2/3 …这些都是数字,数字可以响应很多消息用于计算各种数学表达式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2.

20 factorial.

1000 factorial / 999 factorial.

(1/3).

(1/3) + (4/5).

(1/3) asFloat.

1 class.

1 class maxVal class.

(1 class maxVal + 1) class.

字符类型

字符使用$操作符

1
2
3
4
5
6
7
8
9
$A.

$A class.

$B charCode.

Character cr.

Character space.

我们可以打印256个Ascii字符

1
Character allByteCharacters.

字符串类型

字符串是一个字符集合,使用'单引号将字符集合括起来即可

1
2
3
4
5
6
7
'ProfStef'.

'ProfStef' size.

'abc' asUppercase.

'Hello World' reverse.

我们可以使用at:消息来访问字符串中的任意字符

1
'ProfStef' at: 1.

字符串拼接可以使用,操作符

1
'ProfStef', ' is cool'.

符号类型

符号是保证全局唯一的字符串。只有一个#Symbol符号对象,但是可以有多个'Symbol'字符串对象

(Message == returns true if the two objects are the SAME)

1
2
3
4
5
6
7
'ProfStef' asSymbol.

#ProfStef asString.

(2 asString) == (2 asString).

(2 asString) asSymbol == (2 asString) asSymbol.

数组类型

静态数组在解析期间被创建

1
2
3
4
5
6
7
8
9
#(1 2 3).

#(1 2 3 #(4 5 6)) size.

#(1 2 4) isEmpty.

#(1 2 3) first.

#('hello' 'World') at: 2 put: 'Pharo'; yourself.

动态数组在执行期间被创建

1
2
3
{ (2+3) . (6*6) }.

{ (2+3) . (6*6) . 'hello', ' Stef'} size.

消息

消息会被发送给对象,在Smalltalk中有三种类型的消息:一元unary、二元(binary)和关键字(keyword)

一元(Unary)消息的形式:anObject aMessage

1
2
3
4
5
6
7
8
9
1 class.

false not.

Time now.

Date today.

Float pi.

二元(Binary)消息的形式:anObject + anotherObject

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
3 * 2.

Date today + 3 weeks.

false | false.

true & true.

true & false.

10 @ 100.

10 <= 12.

'ab', 'cd'.

Date today < Date yesterday.

关键字(Keyword)消息的形式:anObject akey: anotherObject akey2: anotherObject2

1
4 between: 0 and: 10.

这个是将between:and:消息发送给数字4

1
2
3
1 max: 3.

Color r:1 g:0 b:0.

这里消息r:g:b:是由Color类实现的,我们也可以写成下面这种形式

1
2
3
4
Color
r:1
g:1
b:0.

消息优先级

一元消息会最先执行,接着执行二元消息,最后才会执行关键字消息

  • 一元(Unary) > 二元(Binary) > 关键字(Keywords)
1
2
3
2 + 3 squared.

2 raisedTo: 3 + 2.

在具有相似优先级的消息之间,表达式从左到右执行

1
-3 abs negated reciprocal.

可以使用括号更改求值顺序

1
2
3
(2 + 3) squared.

(2 raisedTo: 3) + 2.

传统的数学优先规则不适用于Smalltalk

1
2 * 10 + 2.

这里消息 * 被发送到 2,2 回答 20,然后 20 接收消息 +

1
2
3
4
5
6
7
8
9
2 + 2 * 10.

2 + (2 * 10).

8 - 5 / 2.

(8 - 5) / 2.

8 - (5 / 2).

记住,所有消息都遵循一个简单的从左到右的优先规则,没有例外

;运算符

; 是级联运算符,在向同一个接收者发送消息时非常有用

1
2
3
Transcript show: 'hello'.
Transcript show: 'Pharo'.
Transcript cr.

这段代码等价于下面的写法

1
2
3
4
Transcript
show: 'hello';
show: 'Pharo' ;
cr.

块(Blocks)是匿名方法,可以存储到变量中并在需要的时候才执行

块被包含在一对方括号中:[]

1
[:x | x+2].

这里有一个块,功能是对传入的参数做加2操作(这里的参数被命名为 x),这里并不会真的执行块

1
[:x | x+2] value: 5.

当我们想执行块的时候,需要向块发送 value 消息

1
2
3
[:x | x+2] value: 10.

[:x :y| x + y] value: 3 value: 5.

块可以分配给变量,并延迟执行

通过 | b | 来声明变量 b,并使用 := 操作符来为变量赋值

1
2
3
|b|
b := [:x | x+2].
b value: 12.

条件分支

条件语句只是给布尔对象发送消息

1
2
3
1 < 2
ifTrue: [100]
ifFalse: [42].

这里的消息是 ifTrue:ifFalse:

1
2
3
3 > 10
ifTrue: [Transcript show: 'Maybe there''s a bug ....']
ifFalse: [Transcript show: 'No: 3 is less than 10'].

循环

循环是高级集合迭代器,作为常规方法实现

1
2
to:do:
to:by:do:

标准循环写法:

1
2
3
4
5
1 to: 100 do: [:i | Transcript show: i asString; cr].

1 to: 100 by: 3 do: [:i | Transcript show: i asString; cr].

100 to: 0 by: -2 do: [:i | Transcript show: i asString; cr].

消息 do: 被发送到集合对象(ArraySetOrderedCollection),为每个元素计算块

1
2
#(11 38 3 -2 10) do: [:each |
Transcript show: each printString; cr].

除了 do: 之外,还有许多其他好用的迭代器

1
2
3
4
5
6
7
8
9
10
11
12
13
#(11 38 3 -2 10) collect: [:each | each abs].

#(11 38 3 -2 10) collect: [:each | each odd].

#(11 38 3 -2 10) select: [:each | each odd].

#(11 38 3 -2 10) select: [:each | each > 10].

#(11 38 3 -2 10) reject: [:each | each > 10].

#(11 38 3 -2 10)
do: [:each | Transcript show: each printString]
separatedBy: [Transcript show: '.'].

对象

对象是一个类的实例。通常,我们将new消息发送给类来创建一个对象实例

1
2
3
SimpleButtonMorph new
label: 'A nice button';
openCenteredInWorld.

如果向类发送allInstances消息,类将回应一个包含该类所有实例的数组

1
SimpleButtonMorph allInstances size.

反射

你可以在运行时检查和更改系统

查看True类的方法ifFalse:ifTrue:的源码

1
(True>>#ifFalse:ifTrue:) definition.

也可以查看注释

1
(True>>#ifFalse:ifTrue:) comment.

使用respondsTo检查是否能够响应消息

1
ProfStef respondsTo: #goToNextLesson.

删除一个方法

1
ProfStef class removeSelector: #goToNextLesson.

Pharo环境

Pharo是一个完整的环境,拥有诸如:窗口、文本、数字、日期、颜色、点等等。与其他编程语言相比,您可以更直接地与对象交互

每个对象都理解消息inspect,因此,你将获得一个Inspector窗口,该窗口可以显示有关对象的详细信息

1
Date today inspect.

调试Debugger

调试器可能是Smalltalk环境中最著名的工具。一旦发生异常它将立即打开。

下面的代码将打开消息堆栈上的调试器,选择PharoSyntaxTutorial>>dividetwoyzero

1
PharoSyntaxTutorial new divideTwoByZero.