ios 开发iOS安安IOS

Swift 十二讲 第二章 常量变量类型元组字符串和操作符

2015-01-30  本文已影响465人  zydscience

(Draft)

1. 类型,常量,变量

Swift包含各种常见数据类型。例如各种有无符号的32位,64位整数,浮点数,布尔数等等。数据类型的max,min属性用来报告数据类型的最大最小区间。例如:

Int.max 
//Playground里显示答案:9,223,372,036,854,775,807

0b,0o,0x分别用来表示二进制,八进制,十六进制数。Swift也支持1.2e4这样的缩写。详细细节可以参考官方手册。

    typealias 短整数 = UInt8
    var cc : 短整数 = 105 
    //注意不要使用中文输入法里的等号;注意别忘了等号前后的空格

上面这段代码,用关键字typealias定义了一个“短整数”类型别名。然后定义了一个变量cc,其类型为“短整数”。cc被初始化为数值105。

2.变量和常量

var a = 1
var a: Int = 1

或者

var a: Int
a=1

很显然,最好用的是var a=1。 Swift会自行推断类型。注意,初始化不是必须的。上面例子是为了说明简洁。
变量用var关键字。常量用let关键字。例如:

let k = 1
let kk : Float = 3.14

常量不能被改变。所以它在声明的时候,必须被赋值。如上面的例子所示,常量的类型推断使用起来也非常方便。

var ax : Int
{return 20}
ax+ax //Playground显示结果为40

你还可以在上例的大括号中使用get和set函数。但作者认为这两个函数在这里用处不大。就不展开了。有兴趣的读者可以在Playground试验。

*willset和didset这两个函数可以在变量被声明的时候附带定义。如果使用变量观测器,变量类型必须被显式指定,而且必须被初始化。如下例:

var a : Int = 0
{
willSet
    {println("a将被赋值")}
didSet 
{println("a已经被赋值")}
}

a = 0 //Playground的console会显示"a将被赋值"和"a已经被赋值"两行字

作者个人认为,计算变量,willSet和didSet是面向对象风格的语言要素。传统语言例如c的变量声明是不包含这些部分的。对变量来说,这三个东西的用处不大,还说不定容易引起混乱。但后面读者会看到。类的属性也使用类似的语法,那里就非常关键了。

2.元组(Tuples)

var a = ("狗", 1, 2.3) //使用类型推断定义了一个元组变量
println(a.0) //用位置表示元组中的单个元素,console输出为“狗”

你也可以用下面方法定义元组。效果是一样的。

var a : (String, Int, Float)
a = ("狗", 1, 2.3)
println(a.0)
var a:(动物种类 : String, 年龄 : Int, 毛长 : Float)
a = ("狗", 1, 2.3)
println(a.动物种类) 
//a.0 和 a.动物种类 是同一个元素的名字。后者更直观而已。
typealias 动物 = (动物种类 : String, 年龄 : Int, 毛长 : Float)
var a:动物
a = ("狗", 1, 2.3)
println(a.动物种类) 

3.操作符

操作符被用来指明作用于被操作的语言名词上的一些操作。例如加减乘除,绝对值等等。这些定义都和C语言类似。Swift也支持位运算,以及=++,++等操作符。这些常用的操作符,笔者就不抄写手册了。但有以下几点,笔者认为应该特别注意。

println(0&/0) //输出是0。Swift的溢出除法规定被0除返回0
 for i in 1...5
{
println(i)
}   //将输出1,2,3,4,5

也可以用小于号和两个点:

 for i in 1..<6
{
println(i)
}   //将输出1,2,3,4,5

expr1? expr_A:expr_B

上面描述的意思是,如果条件表达式expr1的值为真,则执行expr_A的代码段。不然就执行expr_B。例如:

var a = 10
a == 1 ? println(a) : println(-a)

//输出是-10

4. 字符串的加减,比较,传递和\操作

let a = "我是" + "一个" + "好人"
println(a) //输出为:我是一个好人
println(countElements("我是一个好人")) //输出为6

==表示字符相等。!=表示不等。如果一个字符串字典序在另一个之前,那么前者为小,例如:

println("blue"<"dog") //输出为true

println(("好人"<"坏人")) //输出为false。
//中文字符串的字典序很不直观啊。谁能告诉我为什么好人小于坏人...

字符串有两个内建属性函数: hasPrefix和hasSuffix。
下面例子可以明确说明字符串前后缀判断函数的用法:

println(("好人".hasPrefix("好")))  //输出为true
println(("好人不坏".hasSuffix("坏"))) //输出为true

我个人认为,Escape符号在编译器里面的用法,是计算机科学最简单明了,但又最深的部分之一。绝对不要小瞧了它。

Ken Thmpson的图灵奖讲话:
http://cm.bell-labs.com/who/ken/trust.html
This is an amazing piece of code. It "knows" in a completely portable way what character code is compiled for a new line in any character set. The act of knowing then allows it to recompile itself, thus perpetuating the knowledge.

这个东西的原理很简单,当编译器读到你代码里的一个\的时候,它会再读下一个字符,然后才能决定前一个字符的意思。如果是两个\,那么它的意思就是一个\。如果是\n,因为只有一个,所以它的意思就是\n本身,也就是line feed。

所以编译器对\的翻译需要两次扫描,第一次先走到\后面的字符,然后再回来决定前一个\的意思。这种两次扫描的办法,是所有编译器最基本的原理的一部分。有了这个办法,你可以逐步扩展你的编译器功能。人常听说"C的编译器是C写的"之类的说法,其根本原理其实就是在于Escape符号的用法。

在Swift里,可以用** "\(expr)" **计算expr的值,然后结果被转换为字符串。下面是一些例子:

println("\(2+3)")  
println("神奇的Escape=\(2+3)")
//上句输出是: 神奇的Escape=5
println("神奇的Escape=\\")
println("神奇的Escape=\\\(2+3)")

还有一个深入一点的例子:

let b = 20
println("\((b == 10) ? 1 : 2)")
//输出为2

记住** "\(expr)" 是个筐,里面什么都能装。当然,虽然 "\(expr)" **结构简单+原理深刻,多试验有助于理解计算机工作原理。但作者不鼓励这么写。

上一篇下一篇

猜你喜欢

热点阅读