zoukankan      html  css  js  c++  java
  • 十七、类型绑定 Type Casting

    1. 概述

    Type Casting 的作用:

    • 1)expression is typeis 检查某个实例的类型。
    • 2)expression as typeas 在编译阶段将某个实例的类型绑定为其他类型来访问,并且总是成功。
    • 3)expression as? typeas? 返回指定类型的可选值。在运行时,如果绑定成功,expression 会被打包为一个可选值返回,如果绑定失败,返回值是nil
    • 4)expression as! typeas! 强制转换 expression 为指定类型,as! 返回的不是可选值,如果绑定失败了,会触发运行时错误。x as! T 与 (x as? T)!是等价的 
    • 5)检查某种类型是否实现了协议的方法。

    2. 引例,定义三个类:

        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")
        ]
        // the type of "library" is inferred to be [MediaItem]

    2.1 检查实例的类型 Checking Type

    使用类型检查操作符(type check operatoris 判断一个实例是否是子类类型。如果是子类类型返回 true,否则返回 false。

    遍历上面的数组:

        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"

    2.2 向下绑定 Downcasting

    一个类实例有时要当做它的子类实例来使用,使用类型绑定操作符(type cast operator) as 来向下绑定到子类类型。

    如果你不确定转换是否会成功,使用可选值形式 as? ,如果失败,返回 nil 。

        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

    注意:类型绑定并没有真的修改实例,仅仅只是把它当做它所绑定的类型来对待和访问。

    3. 绑定为Any和AnyObject类型 Type Casting for Any and AnyObject

    Swift为一些不明确的类型提供了两个特殊的类型别名:

    • 1)AnyObject 可以表示任何类类型的实例(对象类型)。
    • 2)Any 可以表示任何类型,包括函数类型。

    3.1 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的实例类型(对象类型),我们可以将他们向下绑定直接拆包为非可选的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

    也可以使用更简洁的方式——将数组 someObjects的[AnyObject]类型 向下绑定为 [Movie]类型:

        for movie in someObjects 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

    3.2 Any 类型

    比如:

        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)" })

    遍历数组:

        for thing in things {
          switch thing {
            case 0 as Int:
              println("zero as an Int")
            case 0 as Double:
              println("zero as a Double")
            case let someInt as Int:
              println("an integer value of (someInt)")
            case let someDouble as Double where someDouble > 0:
              println("a positive double value of (someDouble)")
            case is Double:
              println("some other double value that I don't want to print")
            case let someString as String:
              println("a string value of "(someString)"")
            case let (x, y) as (Double, Double):
              println("an (x, y) point at (x), (y)")
            case let movie as Movie:
              println("a movie called '(movie.name)', dir. (movie.director)")
            case let stringConverter as String -> String:
              println(stringConverter("Michael"))
            default:
              println("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

    注意:在上面的代码中使用的是强制绑定as而不是可选的绑定as?,因为在在switch的case语句中使用强制的as永远是安全的。

    参考自:https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/TypeCasting.html#//apple_ref/doc/uid/TP40014097-CH22-ID338

  • 相关阅读:
    Delphi使用资源文件全攻略
    Javascript URL编码方法的比较
    评论:人才流失强力折射出现实畸形人才观
    AJAX从服务端获取数据的三种方法
    Builder 生成器模式(创建型模式)
    tsql中使用参数设置取值范围
    无法使用多维数据库模型创建报表模型
    报表模型_继承其他实体的属性
    Adapter 适配器(结构型模式)
    报表模型_指定点击链接型报表选项
  • 原文地址:https://www.cnblogs.com/actionke/p/4267961.html
Copyright © 2011-2022 走看看