十七、类型绑定 Type Casting

1. 概述

Type Casting 的作用:

  • 1)检查某个实例的类型。使用 is 关键字。
  • 2)将某个实例的类型绑定为其他类型来访问。使用 as 关键字。
  • 3)检查某种类型是否实现了协议的方法。

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

时间: 2024-08-29 05:21:40

十七、类型绑定 Type Casting的相关文章

[anyObject] 类型推断 Type Casting

在swift 中,如果遍历一个集合,可能就需要用到类型推断 方式一:先把一个确定的集合进行推断,之后在遍历,适合单一的元素类型. let constraints = self.constraints() as! [NSLayoutConstraint]; var item : NSLayoutConstraint? = nil; for constraint in constraints { if constraint.firstAttribute == attribute && cons

Struts2-学习笔记系列(9)-OGNL类型转换和类型绑定

HTML: 1 <s:form action="login"> 2 <s:textfield name="user.name" label="用户名"></s:textfield> 3 <s:textfield name="user.pwd" label="密码"></s:textfield> 4 <s:submit value="

Swift 集合类型(Collection Type) 之 字典(dictionary)(官方文档翻译及总结)

Swift语言提供经典的数组和字典两种集合类型来存储集合数据.数组和字典中存储的数据值类型必须明确.这意味着我们不能把不正确的数据类型插入其中.Swift对显式类型集合的使用确保了我们的代码对工作所需要的类型非常清楚.也让我们在开发中可以早早的找到任何的类型不匹配错误.如果你用变量(var)创建的集合,这些集合就是可变的(增删改).如果用常理创建的,这些集合是不能被操作的. 注意: 如果集合的元素是不变的,那就将集合声明为常量.这样Swift编译器能对你创建的集合做性能优化. 1. 数组(arr

Java-泛型编程-类型擦除(Type Erasure)

Java中的泛型代码和C++中的模板有一个很大的不同:C++中模板的实例化会为每一种类型都产生一套不同的代码,这就是所谓的代码膨胀. Java中并不会产生这个问题.虚拟机中并没有泛型类型对象,所有的对象都是普通类. 虚拟机中的泛型转换需要记住4条事实: 1) 定义任何一个泛型都会自动产生其原始类型(raw type) 2) 这个过程中,泛型类型会被擦除,替换为其限定类型(bounding type) 3) 必要时插入强制转换来保证类型安全 4) 使用桥接方法(bridge method)来保证正

springmvc如何将form表单中的对象类型绑定

原文:springmvc如何将form表单中的对象类型绑定 代码下载地址:http://www.zuidaima.com/share/1550463256054784.htm 比如用户编辑视频,该视频输入某个分类,编辑视频的表单如下: <form> <select name="category"> <option value="yule">娱乐</option> <option value="keji&

Swift Programming Language ——实例方法(Instance Methods)和类型方法(Type Methods)

方法是与某些特定类型相关联的函数.类.结构体.枚举都可以定义实例方法:实例方法为给定类型的实例封装了具体的任务与功能.类.结构体.枚举也可以定义类型方法:类型方法与类型本身相关联.类型方法与 Objective-C 中的类方法(class methods)相似. 结构体和枚举能够定义方法是 Swift 与 C/Objective-C 的主要区别之一.在 Objective-C 中,类是唯一能定义方法的类型.但在 Swift 中,你不仅能选择是否要定义一个类/结构体/枚举,还能灵活的在你创建的类型

Java如何获取Content-Type的文件类型Mime Type

在Http请求中,有时需要知道Content-Type类型,尤其是上传文件时,更为重要,虽然有些办法可以解决,但都不太准确或者繁琐,索性我发现一个开源的类库能够解决相对完美的解决这个问题,它就是jMimeMagic. jMimeMagic是一个用来检测文件或者数据流的 MIME 类型的 Java 类库. 最新版本是V 0.1.2.需要jar包:commons-logging-1.0.x.jar,log4j-1.2.x.jar 下载地址:点击打开链接 它的用法很简单,如下: File file =

201507010852_《Javascript权威指南(第六版)——判断值类型的type函数 、鸭式辩型》(P210-217)

一. 类的扩充 1. 只要扩充原型类,就能动态更新到实例.例如:xxx.prototype.do = function() {//...}; 2. 不建议采用污染JavaScript的方法,如:Object.prototype.methods = function() {//...};   采用<权威指南>9.8.1中的方法添加属性,如:Object.defineProperty(//...); 3. 二. 类和类型 1. isPrototypeOf(); 2. 三. constructor属

父类通过泛型获得子类Class类型 以及Type体系

1.背景介绍 在实现SSH框架中,DAO层向数据库持久化的过程中,因为大部分保存对象的方法都会调用到sava():所有索性就把save delete update select 方法进行封装到父类中,这时候就遇到了个问题,子类在调用这些方法的时候,需要根据子类的类型获知子类Class类型:这个时候可以通过传入泛型,根据泛型的类型来获取子类的Class类型:  2.实现代码范例 父类:public abstract class Parents<E> { private Class<?>