原始
在我的项目中,我有一个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)
}
现在我收到一个错误:无法表达元组转换&#39;([WeaponItems],Int, 字符串)&#39; to&#39;([Items],Int,String)&#39;
传递给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
}
...
}
答案 0 :(得分: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)
}
..也应该有帮助。