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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容