美文网首页
Swift:枚举和结构体

Swift:枚举和结构体

作者: 厨子 | 来源:发表于2016-04-21 16:37 被阅读68次
    Enumerations and Structures

    github:Swift基础实例
    github:SwiftBasicTableView

    枚举
    1. 枚举
      enum 创建一个枚举,与类和所有其他指定的类型一样,枚举可以拥有和它相关联的方法:
    enum Rank: Int {
        
        case Ace = 1
        case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten
        case Jack, Queen, King   
    }
    

    让它包含一个和它关联的方法 simpleDescription()

    enum Rank: Int {
        //enum case must declare a raw value when the preceding raw value is not an integer
        case Ace = 1
        case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten
        case Jack, Queen, King
        func simpleDescription() ->String {
            switch self {
            case .Ace:
                return "ace"
            case .Jack:
                return "jack"
            case .Queen:
                return "queen"
            case .King:
                return "king"
            default:
                return String(self.rawValue)
            }
        }
    }
    let ace = Rank.Ace
    let aceRawValue = ace.rawValue          //1
    let aceString = ace.simpleDescription() //"ace"
    
    • 上面代码中 case Ace = 11Ace 的原始值,称为rawValue,类型是 Int,后面的枚举值依次递增,如Two就是2,依次类推。
    • 枚举的类型也可以 StringFloat类型,但是除了 Int类型之外,其他类型的rawValue 都不可以递增,每一个 enum case 都需要指定一个相应类型的值作为它的 rawValue
    1. 枚举构造器
      带有rawValueenum会自动接收一个可失败构造器 init?(rawValue:),它根据枚举其中一个 raw value,找到合适的case,生成枚举的实例对象;如果没有匹配到合适的case,则返回nil
    let convertRank = Rank(rawValue: 3)
    if  convertRank != nil {
          let threeDescription = convertRank.simpleDescription()
          print(threeDescription) //"3"
    }
    else {
          print("Have no this enum")
    }
    
    1. 枚举的值
      在枚举中 case 后的值就是枚举实际的值,不仅仅是它们的raw value 的另一种写法。实际上,也可以不为枚举提供 raw value
    enum Suit {
        case Spades, Hearts, Diamonds, Clubs
        func simpleDescription() ->String {
            switch self {
            case .Spades:
                return "spades"
            case .Hearts:
                return "hearts"
            case .Diamonds:
                return "diamonds"
            case .Clubs:
                return "clubs"
            }
        }
    }
    let hearts = Suit.Hearts
    // 在这个枚举中,我们没有提供 `raw value` ,当强行调用 rawValue 时,编译器会把 `rawValue` 当做一个成员变量,因此会报错:找不到这个成员
    // let rawValue = hearts.rawValue; 
    let heartsDes = hearts.simpleDescription() //"hearts"
    

    注意上面 Hearts 有两种被引用方式,第一种是在 switch 中,通过简写形式 .Hearts; 第二种是通过 Suit.Hearts,给 hearts赋值。第一种是因为通过 self 已经知道是 Suit,所以可以使用简写形式.Hearts;第二种由于 hearts 没有明确给出类型,所以只能写全名。因此,以下的写法也是对的:
    switch self { case Suit.Hearts:......}
    let heartAbb: Suit = .Hearts

    1. 枚举的关联值(associated values)
      枚举的 case 值可以存储一些和它相关的其他类型的值,称为关联值(associated values)。
      比如一个商品的条形码,条形码由4部分0-9的数字组成:第一部分是只有1个数字的数字位;第二部分是5个数字的制造位;第三部分是5个数字的产品位;第四部分是1个数字的校验位。一个二维码却可以包含所有一维码的信息,同时还可以包含一些其他信息。我们用枚举的形式来表现这个二维码:
    enum Barcode {
        case UPCA(Int, Int, Int, Int)
        case QRCode(String)
    }
    

    上面代码可以理解为:一个枚举名字叫 Barcode,这个枚举包含一个值 UPCAUPCA有一个类型为(Int, Int, Int, Int) 的关联值,或者包含一个值 QRCode,QRCode 有一个类型为(String)的关联值。生成一个含有关联值的枚举对象:

    var barcode = Barcode.UPCA(9, 72345, 77787, 8)
    //barcode 被替换为QRCode(String),barcode 只能存储其中之一
    barcode = .QRCode("abcdef")
    switch barcode {
    case .UPCA(let numberSystem, let manufacture, let product, let check):
           print("UPC-A: \(numberSystem) \(manufacture) \(product) \(check)")
    case .QRCode(let productCode):
           print("QR Code: \(productCode)")
    }
    //prints "QR Code: abcdef"
    

    如果关联值的类型都是常量(constant)变量(variable),那么只需要在 case 前写一个 letvar ,就可以了:

    switch barcode {
    case let .UPCA(numberSystem, manufacture, product, check):
           print("UPC-A: \(numberSystem) \(manufacture) \(product) \(check)")
    case let .QRCode(productCode):
           print("QR Code: \(productCode)")
    }
    //prints "QR Code: abcdef"
    
    结构体
    • 用关键字 struct 创建一个结构体。
      结构体(struct) 和 类(class)有很多相似的地方,也包含有属性、方法和初始化构造器。主要来看一下它们的不同点:
    • class 有继承,struct 没有
    • runtime 期间,根据 Type casting (类型转换),可以得知一个实例( instance)所属于的类
    • class 有析构函数,struct 没有
    • class 可以使用 ARC

    最重要的,结构体属于值类型,在代码中传递的时候,每次都会被复制(copy)一份,而类是通过引用(reference)传递的:

    struct Card {
        var score : Int
    }
    
    let cart      = Cart(score: 3)
    var varCart   = cart
    varCart.score = 5
    print(cart.score) // 3
    print(varCart.score) // 5
    

    可以看到,我们把对象 cart 赋值给 varCart 后,修改 varCart 的属性值,并不会对 cart 的属性值造成影响。这和下面的 class 完全不同:

    class testInit {
        
        var number = 0
        var point = 9
    }
    
    let testI    = testInit()
    let testII   = testI
    testII.point = 8
    print(testI.point) // 8
    

    当我们把对象 testI 赋值给 testII 后,修改 testII 的属性 point,由于类是引用类型(相应说明参考概念解释),

    通过下面的代码,我们来认识 struct 中很重要的一个概念:成员构造器。(该构造器的说明请参考 概念解释)

    struct Card {
        var rank : Rank
        var suit : Suit    
    
        func simpleDescription()-> String {
            return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
        }
    }
    let threeOfSpades = Card(rank: .Three, suit: .Spades)
    let threeDes = threeOfSpades.simpleDescription() //"The 3 of spades"
    

    上面的代码中,我们使用了函数 Card(_: , _: ) 生成一个对象,此函数是 struct 自动接收的,称为 成员构造器 (Memberwise initializer)

    需要注意到是,上面结构体内的两个属性 ranksuit 在声明时并没有初始化,而是在生成 threeOfSpades 实例对象的时候才初始化,因此,结构体只接收一个成员构造器。如果这两个属性在声明的时候已经初始化,那么,结构体将接收两个构造器:Card()Card(_: , _: ) 。少初始化任何一个属性,都只会接收一个构造器:Card(_: , _: )

    相关文章

      网友评论

          本文标题:Swift:枚举和结构体

          本文链接:https://www.haomeiwen.com/subject/bxoklttx.html