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

(Draft)

1. 类型,常量,变量

  • 数值类型

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

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

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

  • Swift支持Character和String类型。但不区分字母和单字母的字符串。这两种类型都要用双引号。例如:

      var aa : String = "小狗"
      var bb: Character = "A"
    
  • Swift可以给类型起个直观的别名,然后方便使用。例如

    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
typealias 动物 = (动物种类 : String, 年龄 : Int, 毛长 : Float)
var a:动物
a = ("狗", 1, 2.3)
println(a.动物种类) 
  • 显然,Swift的元组是非常强大的。尤其是在一块程序往另一块程序输入输出信息的时候,元组这个容器可以非常好用。但笔者建议,对结构化数据,尽量用专门的结构化数据类型。专门适用的结构化数据类型可能有性能优势。例如整型数组,你写成元组,肯定性能不是很划算。

3.操作符

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

  • Overflow operators
    Swift支持溢出加减乘除。例如溢出除法&/:
println(0&/0) //输出是0。Swift的溢出除法规定被0除返回0
  • 类型检查和转换操作符
    Swift支持三种类型检查和转换操作符:
    is被用来检查是否一个instance属于一个指定的类或者协议
    as被用来转换到一个子类或者协议。
    as?可选转换。如果转换失败,返回nil。
    这些内容会在后面详细解释。读者在此知道有这么回事就好。

  • 范围操作符
    (a...b)表示a到b的所有整数,包含a和b。a必须小于或者等于b。

 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. 字符串的加减,比较,传递和\操作

  • Swift的字符串是实际值类型。每次被传递到一个函数里,都会被复制一份。字符串被传递的不是其地址。

  • 字符串可以做加法。就是把另一个字符串附加到前一个。也可以连加。例如:

let a = "我是" + "一个" + "好人"
println(a) //输出为:我是一个好人
  • countElements(MyStrings)这个函数用来计算字符串包含的字符数,而不是bytes数。例如
println(countElements("我是一个好人")) //输出为6
  • 字符串的比较

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

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

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

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

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

我个人认为,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)" **结构简单+原理深刻,多试验有助于理解计算机工作原理。但作者不鼓励这么写。

你可能感兴趣的:(Swift 十二讲 第二章 常量变量类型元组字符串和操作符)