Swift一般转换为协议失败,使用swift_dynamicCastUnknownClass

时间:2015-01-23 15:29:07

标签: swift generics

以下示例摘自Apple Swift参考指南。我只添加了getHasAreaInstances()和getGenericHasAreaInstances()

import UIKit

@objc protocol HasArea {
  var area: Double { get }
}

@objc protocol HasExtendedArea: HasArea {
  var extendedArea: Double { get }
}

class Circle: HasArea {
  let pi = 3.1415927
  var radius: Double
  var area: Double { return pi * radius * radius }
  init(radius: Double) { self.radius = radius }
}
class Country: HasArea {
  var area: Double
  init(area: Double) { self.area = area }
}

class Continent: HasExtendedArea {
  var area: Double { return 300 }
  var extendedArea: Double { return 3000 }
}

let objects: [HasArea] = [
  Circle(radius: 2.0),
  Country(area: 243_610),
  Continent()
]

for object in objects {
  if let objectWithArea = object as? HasExtendedArea {
    println("Extended Area is \(objectWithArea.area)")
  } else {
    println("Area is not extended")
  }
}
// Extended Area is 300.0
// Area is not extended
// Area is not extended

以下方法返回正确的数组:

func getHasExtendedAreaInstances() -> [HasExtendedArea] {
  var haveArea: [HasExtendedArea] = []

  for object in objects {
    if let objectWithArea = object as? HasExtendedArea {
      haveArea.append(objectWithArea)
    }
  }

  return haveArea
}

let areas = getHasExtendedAreaInstances()
//[Continent]

以下方法返回正确的数组:

func getGenericHasExtendedAreaInstances<T>() -> [T] {
  var haveArea: [T] = []

  for object in objects {
    if let objectWithArea = object as? T {
      haveArea.append(objectWithArea)
    }
  }

  return haveArea
}

let areasGeneric: [HasExtendedArea] = getGenericHasExtendedAreaInstances()
//[Continent]

但是,一旦对泛型类型施加约束,它就不再起作用

func getGenericConstraintHasExtendedAreaInstances<T: HasArea>() -> [T] {
  var haveArea: [T] = []

  for object in objects {
    if let objectWithArea = object as? T {
// the line above fails with swift_dynamicCastUnknownClass
      haveArea.append(objectWithArea)
    }
  }

  return haveArea
}

let areasGenericConstraint: [HasExtendedArea] = getGenericConstraintHasExtendedAreaInstances()

2 个答案:

答案 0 :(得分:2)

你的通用功能毫无意义。什么能解决它?什么会满足它?使用相同的基本声明结构制作一个更简单的示例:它是一个不可能的函数。例如,从这个非泛型函数开始:

class Thing : Printable {
    var description : String {return "thing"}
}
func g() -> [Thing] {
    return [Thing()]
}
let result : [Thing] = g()

现在将g修改为通用,与您的函数完全平行:

class Thing : Printable {
    var description : String {return "thing"}
}
func g<T:Printable>() -> [T] {
    return [Thing()]
}
let result : [Thing] = g()

它没有编译 - 因为没有意义。

答案 1 :(得分:0)

这已在Swift 1.2中修复,在Xcode 6.3 Beta 3上测试

您可以在没有swift编译器失败的情况下指定类型约束