Swift 枚舉、類、結(jié)構(gòu)體

一、枚舉

下面是用枚舉表示指南針?biāo)膫€(gè)方向的例子:

 enum CompassPoint {
      case North
      case South
      case East
      case West
}

注意
與 C 和 Objective-C 不同,Swift 的枚舉成員在被創(chuàng)建時(shí)不會(huì)被賦予一個(gè)默認(rèn)的整型值。在上面的CompassPoint例子中,North,South,East和West不會(huì)被隱式地賦值為0,1,2和3。相反,這些枚舉成員本身就是完備的值,這些值的類型是已經(jīng)明確定義好的CompassPoint類型。

directionToHead = .South
switch directionToHead {
      case .North:
              print("Lots of planets have a north")
      case .South:
              print("Watch out for penguins")
      case .East:
              print("Where the sun rises")
      case .West:
              print("Where the skies are blue")
}

正如在控制流(Control Flow)中介紹的那樣,在判斷一個(gè)枚舉類型的值時(shí),switch語句必須窮舉所有情況。如果忽略了.West這種情況,上面那段代碼將無法通過編譯,因?yàn)樗鼪]有考慮到CompassPoint的全部成員。強(qiáng)制窮舉確保了枚舉成員不會(huì)被意外遺漏。
當(dāng)不需要匹配每個(gè)枚舉成員的時(shí)候,你可以提供一個(gè)default分支來涵蓋所有未明確處理的枚舉成員:

let somePlanet = Planet.Earth
switch somePlanet {
case .Earth:
        print("Mostly harmless")
default:
        print("Not a safe place for humans")
}  

下面是三種特殊的枚舉,涉及到關(guān)聯(lián)值、原始值、遞歸枚舉

1-1、關(guān)聯(lián)值
  enum TestAssociatedValueEnumerations{
      case TestIntType(Int,Int)
      case TestStringType(String)
   }

    var testOne = TestAssociatedValueEnumerations.TestIntType(10, 5)
    testOne = .TestStringType("testString")
    /*
    關(guān)聯(lián)值可以被提取出來作為 switch 語句的一部分。你可以在switch的 case 分支代碼中提取每個(gè)關(guān)聯(lián)值作為一個(gè)常量(用let前綴)或者作為一個(gè)變量(用var前綴)來使用
    */
    switch testOne{
        
    case .TestIntType(let numberOne, let numberTwo):
            print("one===\(numberOne),two====\(numberTwo)")
    case .TestStringType(let stringTest):
            print("string ====\(stringTest)")
        
    }

但是這樣老有一個(gè)警告

switch condition evaluates to a constant

原因可能是因?yàn)榫幾g器認(rèn)為我的變量在函數(shù)內(nèi)部一直是不變吧,于是就把變量從函數(shù)內(nèi)部提出來,傳人函數(shù)內(nèi)部,寫成下面這樣,就可以編譯通過沒有任何的warning了.

    // 當(dāng)然在之前得調(diào)用下這個(gè)方法
   testEnum(testOne)
    // 具體的方法
   func testEnum(testOne:TestAssociatedValueEnumerations){
  
    // 為了更加簡潔,也可以下面這樣寫(let 的合理用)
    switch testOne{
    case let .TestIntType(numberOne, numberTwo):
        print("one===\(numberOne),two====\(numberTwo)")
    case let .TestStringType(stringTest):
        print("string ====\(stringTest)")
        } 
    }
1-2、原始值

枚舉成員可以被默認(rèn)值(稱為原始值)預(yù)填充,這些原始值的類型必須相同。

  enum TestRawValueString: String {
          case TestRawOne = "one"
          case TestRawTwo = "Two"
          case TestRawThree = "Three"
  }
1-3、遞歸枚舉

當(dāng)各種可能的情況可以被窮舉時(shí),非常適合使用枚舉進(jìn)行數(shù)據(jù)建模,例如可以用枚舉來表示用于簡單整數(shù)運(yùn)算的操作符。

可以在枚舉類型開頭加上indirect關(guān)鍵字來表明它的所有成員都是可遞歸的:

indirect enum ArithmeticExpression {
      case Number(Int)
      case Addition(ArithmeticExpression, ArithmeticExpression)
      case Multiplication(ArithmeticExpression, ArithmeticExpression)
}

//具體的計(jì)算

override func viewDidLoad() {
    super.viewDidLoad()
    // 計(jì)算 (5 + 4) * 2
    let five = ArithmeticExpression.Number(5)
    let four = ArithmeticExpression.Number(4)
    let sum = ArithmeticExpression.Addition(five, four)
    let product = ArithmeticExpression.Multiplication(sum, ArithmeticExpression.Number(2))
    print(evaluate(product))
   
 }
func evaluate(expression: ArithmeticExpression) -> Int {
    switch expression {
    case .Number(let value):
        return value
    case .Addition(let left, let right):
        return evaluate(left) + evaluate(right)
    case .Multiplication(let left, let right):
        return evaluate(left) * evaluate(right)
    }
}

二、類和結(jié)構(gòu)體

類和結(jié)構(gòu)體有著類似的定義方式。我們通過關(guān)鍵字class和struct來分別表示類和結(jié)構(gòu)體,并在一對大括號中定義它們的具體內(nèi)容:

class SomeClass {
// 類
}
struct SomeStructure {
  // 結(jié)構(gòu)體
}

具體例子

struct testStructFrame {
        var x = 0
        var y = 0
}
class testClassForStudent {
        var name = "Lucy"
        var age = 18
}

 //所有結(jié)構(gòu)體都有一個(gè)自動(dòng)生成的成員逐一構(gòu)造器,用于初始化新結(jié)構(gòu)體實(shí)例中成員的屬性。新實(shí)例中各個(gè)屬性的初始值可以通過屬性的名稱傳遞到成員逐一構(gòu)造器之中:
    let myFrame = testStructFrame(x: 0, y: 0)

 //類和結(jié)構(gòu)體的實(shí)例
    var ourStruct = testStructFrame()
    let ourClass = testClassForStudent()
    // 結(jié)構(gòu)體 引用其屬性,這樣的話,
    ourStruct.y = 100
    ourStruct.x = 20
    // 類 屬性
    ourClass.name = "Yang"
    ourClass.age = 24

// 對比 ourStruct 是 var ,而ourClass 是 let
// 推斷出 結(jié)構(gòu)體是值類型,類是引用類型
// 值類型被賦予給一個(gè)變量、常量或者被傳遞給一個(gè)函數(shù)的時(shí)候,其值會(huì)被拷貝。
// 與值類型不同,引用類型在被賦予到一個(gè)變量、常量或者被傳遞到一個(gè)函數(shù)時(shí),其值不會(huì)被拷貝。因此,引用的是已存在的實(shí)例本身而不是其拷貝。

恒等運(yùn)算符

因?yàn)轭愂且妙愋?,有可能有多個(gè)常量和變量在幕后同時(shí)引用同一個(gè)類實(shí)例。(對于結(jié)構(gòu)體和枚舉來說,這并不成立。因?yàn)樗鼈冏鳛橹殿愋?,在被賦予到常量、變量或者傳遞到函數(shù)時(shí),其值總是會(huì)被拷貝。)
如果能夠判定兩個(gè)常量或者變量是否引用同一個(gè)類實(shí)例將會(huì)很有幫助。為了達(dá)到這個(gè)目的,Swift 內(nèi)建了兩個(gè)恒等運(yùn)算符:

等價(jià)于(===)
不等價(jià)于(!==)

注意 =====,也就是“等于”和“等價(jià)于”的區(qū)別

“等價(jià)于”表示兩個(gè)類類型(class type)的常量或者變量引用同一個(gè)類實(shí)例。
“等于”表示兩個(gè)實(shí)例的值“相等”或“相同”,判定時(shí)要遵照設(shè)計(jì)者定義的評判標(biāo)準(zhǔn),因此相對于“相等”來說,這是一種更加合適的叫法。

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

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

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