精华内容
下载资源
问答
  • Swift 类型转换

    2018-12-21 15:01:00
    Swift 语言类型转换可以判断实例的类型。也可以用于检测实例类型是否属于其父类或者子类的实例。 Swift类型转换使用 is 和 as 操作符实现,is 用于检测值的类型,as 用于转换类型。 类型转换也可以用来检查一个...

    Swift 语言类型转换可以判断实例的类型。也可以用于检测实例类型是否属于其父类或者子类的实例。

    Swift 中类型转换使用 is 和 as 操作符实现,is 用于检测值的类型,as 用于转换类型。

    类型转换也可以用来检查一个类是否实现了某个协议。


    定义一个类层次

    以下定义了三个类:Subjects、Chemistry、Maths,Chemistry 和 Maths 继承了 Subjects。

    代码如下:

    class Subjects {
        var physics: String
        init(physics: String) {
            self.physics = physics
        }
    }
    
    class Chemistry: Subjects {
        var equations: String
        init(physics: String, equations: String) {
            self.equations = equations
            super.init(physics: physics)
        }
    }
    
    class Maths: Subjects {
        var formulae: String
        init(physics: String, formulae: String) {
            self.formulae = formulae
            super.init(physics: physics)
        }
    }
    
    let sa = [
        Chemistry(physics: "固体物理", equations: "赫兹"),
        Maths(physics: "流体动力学", formulae: "千兆赫")]
    
    
    let samplechem = Chemistry(physics: "固体物理", equations: "赫兹")
    print("实例物理学是: \(samplechem.physics)")
    print("实例方程式: \(samplechem.equations)")
    
    
    let samplemaths = Maths(physics: "流体动力学", formulae: "千兆赫")
    print("实例物理学是: \(samplemaths.physics)")
    print("实例公式是: \(samplemaths.formulae)")

    输出:

    实例物理学是: 固体物理
    实例方程式: 赫兹
    实例物理学是: 流体动力学
    实例公式是: 千兆赫

    检查类型

    类型转换用于检测实例类型是否属于特定的实例类型。

    你可以将它用在类和子类的层次结构上,检查特定类实例的类型并且转换这个类实例的类型成为这个层次结构中的其他类型。

    类型检查使用 is 关键字。

    操作符 is 来检查一个实例是否属于特定子类型。若实例属于那个子类型,类型检查操作符返回 true,否则返回 false。

    class Subjects {
        var physics: String
        init(physics: String) {
            self.physics = physics
        }
    }
    
    class Chemistry: Subjects {
        var equations: String
        init(physics: String, equations: String) {
            self.equations = equations
            super.init(physics: physics)
        }
    }
    
    class Maths: Subjects {
        var formulae: String
        init(physics: String, formulae: String) {
            self.formulae = formulae
            super.init(physics: physics)
        }
    }
    
    let sa = [
        Chemistry(physics: "固体物理", equations: "赫兹"),
        Maths(physics: "流体动力学", formulae: "千兆赫"),
        Chemistry(physics: "热物理学", equations: "分贝"),
        Maths(physics: "天体物理学", formulae: "兆赫"),
        Maths(physics: "微分方程", formulae: "余弦级数")]
    
    
    let samplechem = Chemistry(physics: "固体物理", equations: "赫兹")
    print("实例物理学是: \(samplechem.physics)")
    print("实例方程式: \(samplechem.equations)")
    
    
    let samplemaths = Maths(physics: "流体动力学", formulae: "千兆赫")
    print("实例物理学是: \(samplemaths.physics)")
    print("实例公式是: \(samplemaths.formulae)")
    
    var chemCount = 0
    var mathsCount = 0
    for item in sa {
        // 如果是一个 Chemistry 类型的实例,返回 true,相反返回 false。
        if item is Chemistry {
            ++chemCount
        } else if item is Maths {
            ++mathsCount
        }
    }
    
    print("化学科目包含 \(chemCount) 个主题,数学包含 \(mathsCount) 个主题")

    输出:

    实例物理学是: 固体物理
    实例方程式: 赫兹
    实例物理学是: 流体动力学
    实例公式是: 千兆赫
    化学科目包含 2 个主题,数学包含 3 个主题

    向下转型

    向下转型,用类型转换操作符(as? 或 as!)

    当你不确定向下转型可以成功时,用类型转换的条件形式(as?)。条件形式的类型转换总是返回一个可选值(optional value),并且若下转是不可能的,可选值将是 nil。

    只有你可以确定向下转型一定会成功时,才使用强制形式(as!)。当你试图向下转型为一个不正确的类型时,强制形式的类型转换会触发一个运行时错误。

    class Subjects {
        var physics: String
        init(physics: String) {
            self.physics = physics
        }
    }
    
    class Chemistry: Subjects {
        var equations: String
        init(physics: String, equations: String) {
            self.equations = equations
            super.init(physics: physics)
        }
    }
    
    class Maths: Subjects {
        var formulae: String
        init(physics: String, formulae: String) {
            self.formulae = formulae
            super.init(physics: physics)
        }
    }
    
    let sa = [
        Chemistry(physics: "固体物理", equations: "赫兹"),
        Maths(physics: "流体动力学", formulae: "千兆赫"),
        Chemistry(physics: "热物理学", equations: "分贝"),
        Maths(physics: "天体物理学", formulae: "兆赫"),
        Maths(physics: "微分方程", formulae: "余弦级数")]
    
    
    let samplechem = Chemistry(physics: "固体物理", equations: "赫兹")
    print("实例物理学是: \(samplechem.physics)")
    print("实例方程式: \(samplechem.equations)")
    
    
    let samplemaths = Maths(physics: "流体动力学", formulae: "千兆赫")
    print("实例物理学是: \(samplemaths.physics)")
    print("实例公式是: \(samplemaths.formulae)")
    
    var chemCount = 0
    var mathsCount = 0
    
    for item in sa {
        // 类型转换的条件形式
        if let show = item as? Chemistry {
            print("化学主题是: '\(show.physics)', \(show.equations)")
            // 强制形式
        } else if let example = item as? Maths {
            print("数学主题是: '\(example.physics)',  \(example.formulae)")
        }
    }

    输出

    实例物理学是: 固体物理
    实例方程式: 赫兹
    实例物理学是: 流体动力学
    实例公式是: 千兆赫
    化学主题是: '固体物理', 赫兹
    数学主题是: '流体动力学',  千兆赫
    化学主题是: '热物理学', 分贝
    数学主题是: '天体物理学',  兆赫
    数学主题是: '微分方程',  余弦级数

    Any和AnyObject的类型转换

    Swift为不确定类型提供了两种特殊类型别名:

    • AnyObject可以代表任何class类型的实例。
    • Any可以表示任何类型,包括方法类型(function types)。

    注意:
    只有当你明确的需要它的行为和功能时才使用AnyAnyObject。在你的代码里使用你期望的明确的类型总是更好的。

    Any 实例

    class Subjects {
        var physics: String
        init(physics: String) {
            self.physics = physics
        }
    }
    
    class Chemistry: Subjects {
        var equations: String
        init(physics: String, equations: String) {
            self.equations = equations
            super.init(physics: physics)
        }
    }
    
    class Maths: Subjects {
        var formulae: String
        init(physics: String, formulae: String) {
            self.formulae = formulae
            super.init(physics: physics)
        }
    }
    
    let sa = [
        Chemistry(physics: "固体物理", equations: "赫兹"),
        Maths(physics: "流体动力学", formulae: "千兆赫"),
        Chemistry(physics: "热物理学", equations: "分贝"),
        Maths(physics: "天体物理学", formulae: "兆赫"),
        Maths(physics: "微分方程", formulae: "余弦级数")]
    
    
    let samplechem = Chemistry(physics: "固体物理", equations: "赫兹")
    print("实例物理学是: \(samplechem.physics)")
    print("实例方程式: \(samplechem.equations)")
    
    
    let samplemaths = Maths(physics: "流体动力学", formulae: "千兆赫")
    print("实例物理学是: \(samplemaths.physics)")
    print("实例公式是: \(samplemaths.formulae)")
    
    var chemCount = 0
    var mathsCount = 0
    
    for item in sa {
        // 类型转换的条件形式
        if let show = item as? Chemistry {
            print("化学主题是: '\(show.physics)', \(show.equations)")
            // 强制形式
        } else if let example = item as? Maths {
            print("数学主题是: '\(example.physics)',  \(example.formulae)")
        }
    }
    
    // 可以存储Any类型的数组 exampleany
    var exampleany = [Any]()
    
    exampleany.append(12)
    exampleany.append(3.14159)
    exampleany.append("Any 实例")
    exampleany.append(Chemistry(physics: "固体物理", equations: "兆赫"))
    
    for item2 in exampleany {
        switch item2 {
        case let someInt as Int:
            print("整型值为 \(someInt)")
        case let someDouble as Double where someDouble > 0:
            print("Pi 值为 \(someDouble)")
        case let someString as String:
            print("\(someString)")
        case let phy as Chemistry:
            print("主题 '\(phy.physics)', \(phy.equations)")
        default:
            print("None")
        }
    }

    输出:

    实例方程式: 赫兹
    实例物理学是: 流体动力学
    实例公式是: 千兆赫
    化学主题是: '固体物理', 赫兹
    数学主题是: '流体动力学',  千兆赫
    化学主题是: '热物理学', 分贝
    数学主题是: '天体物理学',  兆赫
    数学主题是: '微分方程',  余弦级数
    整型值为 12
    Pi 值为 3.14159
    Any 实例
    主题 '固体物理', 兆赫

    AnyObject 实例

    class Subjects {
        var physics: String
        init(physics: String) {
            self.physics = physics
        }
    }
    
    class Chemistry: Subjects {
        var equations: String
        init(physics: String, equations: String) {
            self.equations = equations
            super.init(physics: physics)
        }
    }
    
    class Maths: Subjects {
        var formulae: String
        init(physics: String, formulae: String) {
            self.formulae = formulae
            super.init(physics: physics)
        }
    }
    
    // [AnyObject] 类型的数组
    let saprint: [AnyObject] = [
        Chemistry(physics: "固体物理", equations: "赫兹"),
        Maths(physics: "流体动力学", formulae: "千兆赫"),
        Chemistry(physics: "热物理学", equations: "分贝"),
        Maths(physics: "天体物理学", formulae: "兆赫"),
        Maths(physics: "微分方程", formulae: "余弦级数")]
    
    
    let samplechem = Chemistry(physics: "固体物理", equations: "赫兹")
    print("实例物理学是: \(samplechem.physics)")
    print("实例方程式: \(samplechem.equations)")
    
    
    let samplemaths = Maths(physics: "流体动力学", formulae: "千兆赫")
    print("实例物理学是: \(samplemaths.physics)")
    print("实例公式是: \(samplemaths.formulae)")
    
    var chemCount = 0
    var mathsCount = 0
    
    for item in saprint {
        // 类型转换的条件形式
        if let show = item as? Chemistry {
            print("化学主题是: '\(show.physics)', \(show.equations)")
            // 强制形式
        } else if let example = item as? Maths {
            print("数学主题是: '\(example.physics)',  \(example.formulae)")
        }
    }
    
    var exampleany = [Any]()
    exampleany.append(12)
    exampleany.append(3.14159)
    exampleany.append("Any 实例")
    exampleany.append(Chemistry(physics: "固体物理", equations: "兆赫"))
    
    for item2 in exampleany {
        switch item2 {
        case let someInt as Int:
            print("整型值为 \(someInt)")
        case let someDouble as Double where someDouble > 0:
            print("Pi 值为 \(someDouble)")
        case let someString as String:
            print("\(someString)")
        case let phy as Chemistry:
            print("主题 '\(phy.physics)', \(phy.equations)")
        default:
            print("None")
        }
    }

    输出:

    实例物理学是: 固体物理
    实例方程式: 赫兹
    实例物理学是: 流体动力学
    实例公式是: 千兆赫
    化学主题是: '固体物理', 赫兹
    数学主题是: '流体动力学',  千兆赫
    化学主题是: '热物理学', 分贝
    数学主题是: '天体物理学',  兆赫
    数学主题是: '微分方程',  余弦级数
    整型值为 12
    Pi 值为 3.14159
    Any 实例
    主题 '固体物理', 兆赫

    在一个switch语句的case中使用强制形式的类型转换操作符(as, 而不是 as?)来检查和转换到一个明确的类型。

    转载于:https://www.cnblogs.com/loaderman/p/10155776.html

    展开全文
  • swift类型转换

    2018-12-17 16:00:47
    类型转换Swift 中使用 is 和 as 操作符实现。这两个操作符提供了一种简单达意的方式去检查值的类型或者转换它的类型。 你也可以用它来检查一个类型是否实现了某个协议,就像在检验协议的一...

    2.19 类型转换

    本页包含内容:

    定义一个类层次作为例子
    检查类型
    向下转型
    Any 和 AnyObject 的类型转换

    类型转换 可以判断实例的类型,也可以将实例看做是其父类或者子类的实例。

    类型转换在 Swift 中使用 is 和 as 操作符实现。这两个操作符提供了一种简单达意的方式去检查值的类型或者转换它的类型。

    你也可以用它来检查一个类型是否实现了某个协议,就像在检验协议的一致性部分讲述的一样。

    定义一个类层次作为例子

    你可以将类型转换用在类和子类的层次结构上,检查特定类实例的类型并且转换这个类实例的类型成为这个层次结构中的其他类型。下面的三个代码段定义了一个类层次和一个包含了这些类实例的数组,作为类型转换的例子。

    第一个代码片段定义了一个新的基类 MediaItem。这个类为任何出现在数字媒体库的媒体项提供基础功能。特别的,它声明了一个 String 类型的 name 属性,和一个 init(name:) 初始化器。(假定所有的媒体项都有个名称。)

    class MediaItem {
        var name: String
        init(name: String) {
            self.name = name
        }
    }
    

    下一个代码段定义了 MediaItem 的两个子类。第一个子类 Movie 封装了与电影相关的额外信息,在父类(或者说基类)的基础上增加了一个 director(导演)属性,和相应的初始化器。第二个子类 Song,在父类的基础上增加了一个 artist(艺术家)属性,和相应的初始化器:

    class Movie: MediaItem {
        var director: String
        init(name: String, director: String) {
            self.director = director
            super.init(name: name)
        }
    }
    
    class Song: MediaItem {
        var artist: String
        init(name: String, artist: String) {
            self.artist = artist
            super.init(name: name)
        }
    }
    

    最后一个代码段创建了一个数组常量 library,包含两个 Movie 实例和三个 Song 实例。library 的类型是在它被初始化时根据它数组中所包含的内容推断来的。Swift 的类型检测器能够推断出 Movie 和 Song有共同的父类 MediaItem,所以它推断出 [MediaItem] 类作为 library 的类型:

    let library = [
        Movie(name: "Casablanca", director: "Michael Curtiz"),
        Song(name: "Blue Suede Shoes", artist: "Elvis Presley"),
        Movie(name: "Citizen Kane", director: "Orson Welles"),
        Song(name: "The One And Only", artist: "Chesney Hawkes"),
        Song(name: "Never Gonna Give You Up", artist: "Rick Astley")
    ]
    // 数组 library 的类型被推断为 [MediaItem]
    

    在幕后 library 里存储的媒体项依然是 Movie 和 Song 类型的。但是,若你迭代它,依次取出的实例会是 MediaItem 类型的,而不是 Movie 和 Song 类型。为了让它们作为原本的类型工作,你需要检查它们的类型或者向下转换它们到其它类型,就像下面描述的一样。

    检查类型

    用类型检查操作符(is)来检查一个实例是否属于特定子类型。若实例属于那个子类型,类型检查操作符返回 true,否则返回 false

    下面的例子定义了两个变量,movieCount 和 songCount,用来计算数组 library 中 Movie 和 Song 类型的实例数量:

    var movieCount = 0
    var songCount = 0
    
    for item in library {
        if item is Movie {
            movieCount += 1
        } else if item is Song {
            songCount += 1
        }
    }
    
    print("Media library contains \(movieCount) movies and \(songCount) songs")
    // 打印 “Media library contains 2 movies and 3 songs”
    

    示例迭代了数组 library 中的所有项。每一次,for-in 循环设置 item 为数组中的下一个 MediaItem

    若当前 MediaItem 是一个 Movie 类型的实例,item is Movie 返回 true,否则返回 false。同样的,item is Song 检查 item 是否为 Song 类型的实例。在循环结束后,movieCount 和 songCount 的值就是被找到的属于各自类型的实例的数量。

    向下转型

    某类型的一个常量或变量可能在幕后实际上属于一个子类。当确定是这种情况时,你可以尝试向下转到它的子类型,用类型转换操作符as? 或 as!)。

    因为向下转型可能会失败,类型转型操作符带有两种不同形式。条件形式as? 返回一个你试图向下转成的类型的可选值。强制形式 as! 把试图向下转型和强制解包(转换结果结合为一个操作。

    当你不确定向下转型可以成功时,用类型转换的条件形式(as?)。条件形式的类型转换总是返回一个可选值,并且若下转是不可能的,可选值将是 nil。这使你能够检查向下转型是否成功。

    只有你可以确定向下转型一定会成功时,才使用强制形式(as!)。当你试图向下转型为一个不正确的类型时,强制形式的类型转换会触发一个运行时错误。

    下面的例子,迭代了 library 里的每一个 MediaItem,并打印出适当的描述。要这样做,item 需要真正作为 Movie 或 Song 的类型来使用,而不仅仅是作为 MediaItem。为了能够在描述中使用 Movie 或 Song 的 director 或 artist 属性,这是必要的。

    在这个示例中,数组中的每一个 item 可能是 Movie 或 Song。事前你不知道每个 item 的真实类型,所以这里使用条件形式的类型转换(as?)去检查循环里的每次下转:

    for item in library {
        if let movie = item as? Movie {
            print("Movie: '\(movie.name)', dir. \(movie.director)")
        } else if let song = item as? Song {
            print("Song: '\(song.name)', by \(song.artist)")
        }
    }
    
    // Movie: 'Casablanca', dir. Michael Curtiz
    // Song: 'Blue Suede Shoes', by Elvis Presley
    // Movie: 'Citizen Kane', dir. Orson Welles
    // Song: 'The One And Only', by Chesney Hawkes
    // Song: 'Never Gonna Give You Up', by Rick Astley
    

    示例首先试图将 item 下转为 Movie。因为 item 是一个 MediaItem 类型的实例,它可能是一个 Movie;同样,它也可能是一个 Song,或者仅仅是基类 MediaItem。因为不确定,as? 形式在试图下转时将返回一个可选值。item as? Movie 的返回值是 Movie? 或者说“可选 Movie”。

    当向下转型为 Movie 应用在两个 Song 实例时将会失败。为了处理这种情况,上面的例子使用了可选绑定(optional binding)来检查可选 Movie 真的包含一个值(这个是为了判断下转是否成功。)可选绑定是这样写的“if let movie = item as? Movie”,可以这样解读:

    “尝试将 item 转为 Movie 类型。若成功,设置一个新的临时常量 movie 来存储返回的可选 Movie 中的值”

    若向下转型成功,然后 movie 的属性将用于打印一个 Movie 实例的描述,包括它的导演的名字 director。相似的原理被用来检测 Song 实例,当 Song 被找到时则打印它的描述(包含 artist 的名字)。

    注意
    转换没有真的改变实例或它的值。根本的实例保持不变;只是简单地把它作为它被转换成的类型来使用。

    Any 和 AnyObject 的类型转换

    Swift 为不确定类型提供了两种特殊的类型别名:

    • Any 可以表示任何类型,包括函数类型。
    • AnyObject 可以表示任何类类型的实例。

    只有当你确实需要它们的行为和功能时才使用 Any 和 AnyObject。在你的代码里使用你期望的明确类型总是更好的。

    这里有个示例,使用 Any 类型来和混合的不同类型一起工作,包括函数类型和非类类型。它创建了一个可以存储 Any 类型的数组 things

    var things = [Any]()
    
    things.append(0)
    things.append(0.0)
    things.append(42)
    things.append(3.14159)
    things.append("hello")
    things.append((3.0, 5.0))
    things.append(Movie(name: "Ghostbusters", director: "Ivan Reitman"))
    things.append({ (name: String) -> String in "Hello, \(name)" })
    

    things 数组包含两个 Int 值,两个 Double 值,一个 String 值,一个元组 (Double, Double),一个Movie实例“Ghostbusters”,以及一个接受 String 值并返回另一个 String 值的闭包表达式。

    你可以在 switch 表达式的 case 中使用 is 和 as 操作符来找出只知道是 Any 或 AnyObject 类型的常量或变量的具体类型。下面的示例迭代 things 数组中的每一项,并用 switch 语句查找每一项的类型。有几个 switch 语句的 case 绑定它们匹配到的值到一个指定类型的常量,从而可以打印这些值:

    for thing in things {
        switch thing {
        case 0 as Int:
            print("zero as an Int")
        case 0 as Double:
            print("zero as a Double")
        case let someInt as Int:
            print("an integer value of \(someInt)")
        case let someDouble as Double where someDouble > 0:
            print("a positive double value of \(someDouble)")
        case is Double:
            print("some other double value that I don't want to print")
        case let someString as String:
            print("a string value of \"\(someString)\"")
        case let (x, y) as (Double, Double):
            print("an (x, y) point at \(x), \(y)")
        case let movie as Movie:
            print("a movie called '\(movie.name)', dir. \(movie.director)")
        case let stringConverter as String -> String:
            print(stringConverter("Michael"))
        default:
            print("something else")
        }
    }
    
    // zero as an Int
    // zero as a Double
    // an integer value of 42
    // a positive double value of 3.14159
    // a string value of "hello"
    // an (x, y) point at 3.0, 5.0
    // a movie called 'Ghostbusters', dir. Ivan Reitman
    // Hello, Michael
    

    注意
    Any类型可以表示所有类型的值,包括可选类型。Swift 会在你用Any类型来表示一个可选值的时候,给你一个警告。如果你确实想使用Any类型来承载可选值,你可以使用as操作符显示转换为Any,如下所示:

    let optionalNumber: Int? = 3
    things.append(optionalNumber)        // 警告
    things.append(optionalNumber as Any) // 没有警告

    如果觉得对你有帮助,可以赏赐点什么,鼓励一下!

    微信支付:   支付宝:

     

    展开全文
  • Swift类型转换

    2019-09-30 03:12:23
    关于「类型转换」(Type Casting),《The Swift Programming Language》描述如下: Type castingis a way to check the type of an instance, and/or to treat that instance as if it is a different ...

    关于「类型转换」(Type Casting),《The Swift Programming Language》描述如下:

    Type casting is a way to check the type of an instance, and/or to treat that instance as if it is a different superclass or subclass from somewhere else in its own class hierarchy.

    在Swift中,有两个关键字与类型转换相关:isas。前者体现的是Swift的内省机制(introspection),用于检查某个实例的类型(类似于OC中的isKindOfClass:isMemberOfClass:);后者用于类型转换,即将某个类型实例转换为其父类的实例或者子类的实例。

    Swift中的类型转换是一个非常容易理解的概念,本文将以代码为辅助对之进行简单阐述。

    首先定义几个类为后文服务:

    // 「媒体」类
    class MediaItem {
        var name: String
        init(name: String) {
            self.name = name
        }
    }
        
    // 「电影」类
    class Movie: MediaItem {
        var director: String
        init(name: String, director: String) {
            self.director = director
            super.init(name: name)
        }
    }
        
    // 「音乐」类
    class Song: MediaItem {
        var artist: String
        init(name: String, artist: String) {
            self.artist = artist
            super.init(name: name)
        }
    }
    然后再创建一个数组实例:
    let library = [
        Movie(name: "Casablanca", director: "Michael Curtiz"),
        Song(name: "Blue Suede Shoes", artist: "Elvis Presley"),
        Movie(name: "Citizen Kane", director: "Orson Welles"),
        Song(name: "The One And Only", artist: "Chesney Hawkes"),
        Song(name: "Never Gonna Give You Up", artist: "Rick Astley")
    ]

    很容易理解,该library的类型是[MediaItem]。站在物理的角度,library中存储的元素要么是Movie类型实例,要么是Song类型实例。但站在逻辑的角度,你若遍历library,则取出的实例会是MediaItem类型的,而不是Movie或者Song。所以,若想让library中的元素基于它们本来的类型处理事情,那么需要检查它们的类型或者向下转换它们的类型到其他类型。

    Checking Type

    用类型检查操作符is来检查一个实例是否属于特定类型。若实例属于那个类型,类型检查操作符返回true,否则返回false。

    如下定义了两个变量,movieCount和songCount,分别用来计算library中Movie和Song类型实例的数量,如下:

    var movieCount = 0
    var songCount = 0
        
    for item in library {
        if item is Movie {
            movieCount++
        } else if item is Song {
            songCount++
        }
    }
        
    println("Media library contains \(movieCount) movies and \(songCount) songs")
    // prints "Media library contains 2 movies and 3 songs"
    Downcasting

    「Downcasting」常常被翻译为「向下转型」。某个常量或变量在逻辑层面可能属于某种类型,但在物理层面可能属于其某个子类类型。上述library中的元素就是这种情况(逻辑层面包含的元素都属于MediaItem类型,但是实际上有的属于Movie类型,有的属于Song类型)。对于这种情况,你可以使用转换操作符as向下转型(譬如MediaItem转Song或Movie)。

    在OC中,类型转换非常简单,譬如:

    UIViewController *VC = [[UIViewController alloc] init];
    UITableViewController *tableVC = (UITableViewController *)VC;
    tableVC.tableView.background = [UIColor whiteColor];

    这段代码当然会通过编译,但是会产生runtime错误,至于原因就不啰嗦了。

    对于Swift也一样,downcasting也可能会失败。不同的是,在OC中,类型转换成功或失败是无法获知的(因为人家是动态语言嘛,类型检测在runtime才会进行);Swift是强类型语言,类型转换成功与否是可以检查到的,简单来说,Swift的downcasting会返回一个optional,若失败了,则该optional的值为nil

    类型转换操作符有两种不同形式:

    • as?,返回一个optional,若转换成功,则包含你期待的类型实例,若失败,则是nil;
    • as!,相当于转换后强制解包,若转换失败,则会造成runtime错误;

    显然,当你不确定是否能转换是否成功时,使用as?;否则,使用as!
    P.S:能不能直接使用as?No!

    下面的示例遍历了上文的library常量,并打印出其中所有元素的描述信息(名字,音乐作者或者电影导演),如下:

    for item in library {
        if let movie = item as? Movie {
            println("Movie: '\(movie.name)', dir. \(movie.director)")
        } else if let song = item as? Song {
            println("Song: '\(song.name)', by \(song.artist)")
        }
    }
        
    /* 输出:
    Movie: 'Casablanca', dir. Michael Curtiz
    Song: 'Blue Suede Shoes', by Elvis Presley
    Movie: 'Citizen Kane', dir. Orson Welles
    Song: 'The One And Only', by Chesney Hawkes
    Song: 'Never Gonna Give You Up', by Rick Astley
    */
    Any and AnyObject

    虽然Swift是强类型语言,但是OC不是啊,譬如OC中数组可以存放允许类型的类对象(不要求类型一致);考虑到兼容性,Swift为不确定类型提供了两种特殊类型:

    • AnyObject可以代表任何类类型的实例;
    • Any可以表示任何类型实例,包括方法/函数类型;

    值得一提的是,AnyObjectAny尽可能少用,毕竟类型越清晰越好,Swift文档是这么描述的:

    Use Any and AnyObject only when you explicitly need the behavior and capabilities they provide. It is always better to be specific about the types you expect to work with in your code.

    AnyObject

    使用Cocoa APIs时,常常会接收到一个[AnyObject]类型的数组,或者说「一个任何对象类型的数组」。这是因为OC没有明确的类型化数组。然而,很多时候我们常常可以确定知道包含在数组(获取其他集合)中元素的确切类型;在这种情况下,可以使用as!来向下对元素类型进行转换(转到比AnyObject更确切的类型)。如下是对AnyObject向下转型的一个栗子:

    let someObjects: [AnyObject] = [
        Movie(name: "2001: A Space Odyssey", director: "Stanley Kubrick"),
        Movie(name: "Moon", director: "Duncan Jones"),
        Movie(name: "Alien", director: "Ridley Scott")
    ]
    因为知道这个数组只包含Movie实例,你可以直接用as!向下转型并解包到Movie类型:
    for object in someObjects {
        let movie  = object as! Movie
        println("Movie: '\(movie.name)', dir. \(movie.director)")
    }
        
    /*输出:
    Movie: '2001: A Space Odyssey', dir. Stanley Kubrick
    Movie: 'Moon', dir. Duncan Jones
    Movie: 'Alien', dir. Ridley Scott
    */

    还有一种更简洁的写法:

    for movie in someObjects as! [Movie] {
        println("Movie: '\(movie.name)', dir. \(movie.director)")
    }
    Any

    AnyAnyObject差不多,只是后者仅限于类类型,前者通吃所有类型。比较简单,这里不赘述了。

    转载于:https://www.cnblogs.com/FightingLuoYin/p/4608176.html

    展开全文
  • swift 类型转换

    2016-06-15 14:29:32
    /**  * 类型转换练习:类型转换是一种检查类实例的方式,并且哦或者也是让实例作为它的父类或者子类的一种方 式  */ ... *类型转换Swift 中使用 is 和 as 操作符实现。这两个操作符

     

        /**

         * 类型转换练习:类型转换是一种检查类实例的方式,并且哦或者也是让实例作为它的父类或者子类的一种方

         */

        func TypeConversion() {

        

          /**

            *类型转换在 Swift 中使用 is as 操作符实现。这两个操作符

    展开全文
  • swift 对象转换In this tutorial, we’ll be looking into the details of Swift Type Casting. Let’s get started on our Xcode Playground! 在本教程中,我们将研究Swift Type Casting的细节。 让我们开始在我们...
  • 细说Swift类型转换

    2016-07-14 11:51:30
    swift类型转换使用is和as操作符实现,这两个操作符提供了一种简单明了的方式去检查值的类型或转换其他类型。   一、定义类层次为实际例子   可以将类型转换用在类和子类的层次结构上,检查特定...
  • 17-Swift类型转换

    2016-07-12 11:01:35
     在swift类型转换使用is和as操作符实现,这两个操作符提供了一种简单明了的方式去检查值的类型或转换其他类型。 一、定义类层次为实际例子 可以将类型转换用在类和子类的层次结构上,检查特定类型实例的类型并且...
  • 类型转换Swift 中使用 is 和 as 操作符实现。这两个操作符提供了一种简单达意的方式去检查值的类型或者转换它的类型。 你也可以用它来检查一个类是否实现了某个协议,就像在 检验协议的一致性部分讲述的...
  • /**  类型转换  在 C语言中是 (类型)表达式  */    var intVar:Int = 9  var floatValue:Double = 3.2     // 这样子直接赋值是不可以的 // 
  • Swift不允许隐式类型转换, 但可以使用显示类型转换(强制类型转换) OC: int intValue = 10; double doubleValue = (double)intValue; Swift: */ var intValue:Int = 10 var doubleValue:Double doubleValue = ...
  • swift类型转换is和as

    2016-11-29 15:32:00
    为什么80%的码农都做不了架构师?>>> ...
  • http://www.zgxue.com/167/1679428.html 转载于:https://www.cnblogs.com/iosshare/p/5095988.html
  • /// 父类 Person class Person { var name: String init(name: String){ self.name = name } }/// 子类 Woman class Woman: Person { var female: String

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 910
精华内容 364
关键字:

swift类型转换