【问题标题】:Cannot express tuple conversion '([Subclass], Int, String)' to '([Superclass], Int, String)'无法将元组转换 '([Subclass], Int, String)' 表示为 '([Superclass], Int, String)'
【发布时间】:2016-10-13 08:51:07
【问题描述】:

原创

在我的项目中,我有一个Iterator 类,它有一个功能:

func iterateItems<T: Items>(iterationItems: [T], removeItem: (T) -> Void, addItem: (T) -> Void, calculateEfficiency: () -> Void) -> [T] {

    ...
    return bestComposition as! [T]
}

在它的子类 WPCalculator 我这样运行它:

func iterateWPItems() -> [Items] {
    return iterateItems(iterationItems: WeaponItems.weaponItems, removeItem: removeWeaponItem, addItem: addWeaponItem, calculateEfficiency: calcWeaponDemage)
}

新代码

那样一切都很好。现在我想把iterateItems 函数改成这样:

func iterateItems<T: Items>(iterationItems: [T], removeItem: (T) -> Void, addItem: (T) -> Void, calculateEfficiency: () -> Void) -> ([T], Int, String) {

    ...
    return (bestComposition as! [T], bestBuildCost, customMessage)
}

然后我相应地更新了WPCalculator

func iterateWPItems() -> ([Items], Int, String) {
    return iterateItems(iterationItems: WeaponItems.weaponItems, removeItem: removeWeaponItem, addItem: addWeaponItem, calculateEfficiency: calcWeaponDemage)
}

现在我收到一个错误:无法表达元组转换 '([WeaponItems], Int, String)' 到 '([Items], Int, String)'

传递给iterateWPItems 的参数是一个WeaponItems 类型的数组,它是Items 的子类,它在原始版本中运行良好,Swift 似乎已经推断出子类到超类的转换,但是当我将它放在新代码中的元组中时,它不起作用。

这是为什么呢?我该如何解决这个问题?

编辑:

WeaponItems

class WeaponItems: Items {

var weaponPower, attackSpeed, criticalChance, criticalDamage, armorPierce: Double

init(name: String, index: Int, price: Int, weaponPower: Double = 0, attackSpeed: Double = 0, criticalChance: Double = 0, criticalDamage: Double = 0, armorPierce: Double = 0, image: UIImage){

    self.weaponPower = weaponPower
    self.attackSpeed = attackSpeed
    self.criticalChance = criticalChance
    self.criticalDamage = criticalDamage
    self.armorPierce = armorPierce
    super.init(name: name, index: index, price: price, image: image)
}
...
}

Items

class Items {

let name: String
let index: Int
let price: Int
let image: UIImage

init(name: String, index: Int, price: Int, image: UIImage) {
    self.name = name
    self.index = index
    self.price = price
    self.image = image
}
...
}

【问题讨论】:

  • 你在哪个 Swift 版本中得到这个? Swift 3 中的一个简单测试对我来说效果很好。
  • @AntonBronnikov 这是 Swift 3
  • 那你的ItemsWeaponItems 是什么样子的?
  • @AntonBronnikov 请查看编辑

标签: ios swift


【解决方案1】:

问题确实与这样一个事实有关,尽管 Swift 可以将 [WeaponItems] 隐式转换为 [Items],但当这些类型作为元组的组件出现时,它就无法做到这一点。例如。看到这个:Tuple "upcasting" in Swift

有几种方法可以“解决”这个问题。

最简单的是:

func iterateWPItems() -> ([Items], Int, String) {
    let (composition, cost, message) = iterateItems(iterationItems: WeaponItems.weaponItems, removeItem: removeWeaponItem, addItem: addWeaponItem, calculateEfficiency: calcWeaponDemage)
    return (composition, cost, message)
}

或者,您可以更改iterateItems 以仅返回您期望的元组,即([Items], Int, String)

func iterateItems<T: Items>(iterationItems: [T], removeItem: (T) -> Void, addItem: (T) -> Void, calculateEfficiency: () -> Void) -> ([Items], Int, String) {
    ...
    return (bestComposition as! [Items], bestBuildCost, customMessage)
}

更好的是,从它的外观来看,我不明白为什么iterateItems 必须是一个通用方法。如果确实如此,那么只需将其更改为:

func iterateItems(iterationItems: [Items], removeItem: (Items) -> Void, addItem: (Items) -> Void, calculateEfficiency: () -> Void) -> ([Items], Int, String) {
    ...
    return (bestComposition as! [Items], bestBuildCost, customMessage)
}

.. 也应该有帮助。

【讨论】:

  • 是的,你是对的,它有效,最后一种方法是最好的,谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多