Swift 十二講 第二章 常量變量類型元組字符串和操作符

(Draft)

1. 類型,常量,變量

  • 數(shù)值類型

Swift包含各種常見數(shù)據(jù)類型。例如各種有無(wú)符號(hào)的32位,64位整數(shù),浮點(diǎn)數(shù),布爾數(shù)等等。數(shù)據(jù)類型的max,min屬性用來報(bào)告數(shù)據(jù)類型的最大最小區(qū)間。例如:

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

0b,0o,0x分別用來表示二進(jìn)制,八進(jìn)制,十六進(jìn)制數(shù)。Swift也支持1.2e4這樣的縮寫。詳細(xì)細(xì)節(jié)可以參考官方手冊(cè)。

  • Swift支持Character和String類型。但不區(qū)分字母和單字母的字符串。這兩種類型都要用雙引號(hào)。例如:

      var aa : String = "小狗"
      var bb: Character = "A"
    
  • Swift可以給類型起個(gè)直觀的別名,然后方便使用。例如

    typealias 短整數(shù) = UInt8
    var cc : 短整數(shù) = 105 
    //注意不要使用中文輸入法里的等號(hào);注意別忘了等號(hào)前后的空格

上面這段代碼,用關(guān)鍵字typealias定義了一個(gè)“短整數(shù)”類型別名。然后定義了一個(gè)變量cc,其類型為“短整數(shù)”。cc被初始化為數(shù)值105。

2.變量和常量

  • 在使用一個(gè)變量或者常量之前,你必須聲明它們。比較下面三種變量聲明然后初始化的方法:
var a = 1
var a: Int = 1

或者

var a: Int
a=1

很顯然,最好用的是var a=1。 Swift會(huì)自行推斷類型。注意,初始化不是必須的。上面例子是為了說明簡(jiǎn)潔。
變量用var關(guān)鍵字。常量用let關(guān)鍵字。例如:

let k = 1
let kk : Float = 3.14

常量不能被改變。所以它在聲明的時(shí)候,必須被賦值。如上面的例子所示,常量的類型推斷使用起來也非常方便。

  • 除了上面和其他語(yǔ)言類似的變量聲明之外,你還可以聲明計(jì)算變量。如下例子:
var ax : Int
{return 20}
ax+ax //Playground顯示結(jié)果為40

你還可以在上例的大括號(hào)中使用get和set函數(shù)。但作者認(rèn)為這兩個(gè)函數(shù)在這里用處不大。就不展開了。有興趣的讀者可以在Playground試驗(yàn)。

*willset和didset這兩個(gè)函數(shù)可以在變量被聲明的時(shí)候附帶定義。如果使用變量觀測(cè)器,變量類型必須被顯式指定,而且必須被初始化。如下例:

var a : Int = 0
{
willSet
    {println("a將被賦值")}
didSet 
{println("a已經(jīng)被賦值")}
}

a = 0 //Playground的console會(huì)顯示"a將被賦值"和"a已經(jīng)被賦值"兩行字

作者個(gè)人認(rèn)為,計(jì)算變量,willSet和didSet是面向?qū)ο箫L(fēng)格的語(yǔ)言要素。傳統(tǒng)語(yǔ)言例如c的變量聲明是不包含這些部分的。對(duì)變量來說,這三個(gè)東西的用處不大,還說不定容易引起混亂。但后面讀者會(huì)看到。類的屬性也使用類似的語(yǔ)法,那里就非常關(guān)鍵了。

2.元組(Tuples)

  • 不同類型的變量或者常量,加上逗號(hào)分隔,加上括號(hào),就構(gòu)成了元組。元組的聲明和初始化方法和變量,常量的風(fēng)格是一致的。假設(shè)你熟悉了變量和常量,那么下面例子,一看就可以懂。
var a = ("狗", 1, 2.3) //使用類型推斷定義了一個(gè)元組變量
println(a.0) //用位置表示元組中的單個(gè)元素,console輸出為“狗”

你也可以用下面方法定義元組。效果是一樣的。

var a : (String, Int, Float)
a = ("狗", 1, 2.3)
println(a.0)
  • 元組的單個(gè)元素還可以有個(gè)名字,你可以用名字而不是位置來指出這個(gè)元素。
var a:(動(dòng)物種類 : String, 年齡 : Int, 毛長(zhǎng) : Float)
a = ("狗", 1, 2.3)
println(a.動(dòng)物種類) 
//a.0 和 a.動(dòng)物種類 是同一個(gè)元素的名字。后者更直觀而已。
  • 你可以對(duì)元組的類型使用類型別名,也就是關(guān)鍵字typealias
typealias 動(dòng)物 = (動(dòng)物種類 : String, 年齡 : Int, 毛長(zhǎng) : Float)
var a:動(dòng)物
a = ("狗", 1, 2.3)
println(a.動(dòng)物種類) 
  • 顯然,Swift的元組是非常強(qiáng)大的。尤其是在一塊程序往另一塊程序輸入輸出信息的時(shí)候,元組這個(gè)容器可以非常好用。但筆者建議,對(duì)結(jié)構(gòu)化數(shù)據(jù),盡量用專門的結(jié)構(gòu)化數(shù)據(jù)類型。專門適用的結(jié)構(gòu)化數(shù)據(jù)類型可能有性能優(yōu)勢(shì)。例如整型數(shù)組,你寫成元組,肯定性能不是很劃算。

3.操作符

操作符被用來指明作用于被操作的語(yǔ)言名詞上的一些操作。例如加減乘除,絕對(duì)值等等。這些定義都和C語(yǔ)言類似。Swift也支持位運(yùn)算,以及=++,++等操作符。這些常用的操作符,筆者就不抄寫手冊(cè)了。但有以下幾點(diǎn),筆者認(rèn)為應(yīng)該特別注意。

  • Overflow operators
    Swift支持溢出加減乘除。例如溢出除法&/:
println(0&/0) //輸出是0。Swift的溢出除法規(guī)定被0除返回0
  • 類型檢查和轉(zhuǎn)換操作符
    Swift支持三種類型檢查和轉(zhuǎn)換操作符:
    is被用來檢查是否一個(gè)instance屬于一個(gè)指定的類或者協(xié)議
    as被用來轉(zhuǎn)換到一個(gè)子類或者協(xié)議。
    as?可選轉(zhuǎn)換。如果轉(zhuǎn)換失敗,返回nil。
    這些內(nèi)容會(huì)在后面詳細(xì)解釋。讀者在此知道有這么回事就好。

  • 范圍操作符
    (a...b)表示a到b的所有整數(shù),包含a和b。a必須小于或者等于b。

 for i in 1...5
{
println(i)
}   //將輸出1,2,3,4,5

也可以用小于號(hào)和兩個(gè)點(diǎn):

 for i in 1..<6
{
println(i)
}   //將輸出1,2,3,4,5
  • 分支選擇操作符

expr1? expr_A:expr_B

上面描述的意思是,如果條件表達(dá)式expr1的值為真,則執(zhí)行expr_A的代碼段。不然就執(zhí)行expr_B。例如:

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

//輸出是-10

4. 字符串的加減,比較,傳遞和\操作

  • Swift的字符串是實(shí)際值類型。每次被傳遞到一個(gè)函數(shù)里,都會(huì)被復(fù)制一份。字符串被傳遞的不是其地址。

  • 字符串可以做加法。就是把另一個(gè)字符串附加到前一個(gè)。也可以連加。例如:

let a = "我是" + "一個(gè)" + "好人"
println(a) //輸出為:我是一個(gè)好人
  • countElements(MyStrings)這個(gè)函數(shù)用來計(jì)算字符串包含的字符數(shù),而不是bytes數(shù)。例如
println(countElements("我是一個(gè)好人")) //輸出為6
  • 字符串的比較

==表示字符相等。!=表示不等。如果一個(gè)字符串字典序在另一個(gè)之前,那么前者為小,例如:

println("blue"<"dog") //輸出為true

println(("好人"<"壞人")) //輸出為false。
//中文字符串的字典序很不直觀啊。誰(shuí)能告訴我為什么好人小于壞人...
  • 字符串的前后綴

字符串有兩個(gè)內(nèi)建屬性函數(shù): hasPrefix和hasSuffix。
下面例子可以明確說明字符串前后綴判斷函數(shù)的用法:

println(("好人".hasPrefix("好")))  //輸出為true
println(("好人不壞".hasSuffix("壞"))) //輸出為true
  • Escape符號(hào)

我個(gè)人認(rèn)為,Escape符號(hào)在編譯器里面的用法,是計(jì)算機(jī)科學(xué)最簡(jiǎn)單明了,但又最深的部分之一。絕對(duì)不要小瞧了它。

Ken Thmpson的圖靈獎(jiǎng)講話:
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.

這個(gè)東西的原理很簡(jiǎn)單,當(dāng)編譯器讀到你代碼里的一個(gè)\的時(shí)候,它會(huì)再讀下一個(gè)字符,然后才能決定前一個(gè)字符的意思。如果是兩個(gè)\,那么它的意思就是一個(gè)\。如果是\n,因?yàn)橹挥幸粋€(gè),所以它的意思就是\n本身,也就是line feed。

所以編譯器對(duì)\的翻譯需要兩次掃描,第一次先走到\后面的字符,然后再回來決定前一個(gè)\的意思。這種兩次掃描的辦法,是所有編譯器最基本的原理的一部分。有了這個(gè)辦法,你可以逐步擴(kuò)展你的編譯器功能。人常聽說"C的編譯器是C寫的"之類的說法,其根本原理其實(shí)就是在于Escape符號(hào)的用法。

  • 字符串的插值

在Swift里,可以用** "\(expr)" **計(jì)算expr的值,然后結(jié)果被轉(zhuǎn)換為字符串。下面是一些例子:

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

還有一個(gè)深入一點(diǎn)的例子:

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

記住** "\(expr)" 是個(gè)筐,里面什么都能裝。當(dāng)然,雖然 "\(expr)" **結(jié)構(gòu)簡(jiǎn)單+原理深刻,多試驗(yàn)有助于理解計(jì)算機(jī)工作原理。但作者不鼓勵(lì)這么寫。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容