在充满自定义对象的模型中获取第一个不为 nil 的值

Get first value that is not nil in a model full of custom objects

所以我有这个模型:

public class Loot {

    let sword: Sword?
    let armor: Armor?

    init(sword: Sword? = nil, armor: Armor? = Armor()) {
        self.sword = sword
        self.armor = armor
    }
}

所有这些属性都继承自 Item class。

在这个模型中,我将始终只有 1 个属性不为零。有什么办法可以取到这个吗?

使用这个:

extension Sequence where Element == Loot {

        var items: [Item] {
            var internaltems: [Item] = []
            for loot in self {
                let mirror = Mirror(reflecting: loot)
                let item = mirror.children.first { (label, value) -> Bool in
                    let internalValue = value as? Item
                    return internalValue != nil
                }
                if let item = item {
                    internaltems.append(item.value as! Item)
                }
            }
            return internaltems
        }
}

我可以得到第一个不是 nil 的对象和它的 Item 基数。在提示中用 po loots.items 打印出来我实际上可以看到它是一个 Armor 对象。但它仍然是一个 Item 对象,所以我无法访问 Armor 属性。

您可以拥有一个通用 class 只有一个强制性 属性,而不是持有两个属性,其中只有一个已设置。这样您就不必检查已设置或未设置的内容

class Loot<T: Item> {
    let item: T

    init(item: T) {
        self.item = item
    }
}

示例

let loot1 = Loot(item: Armor())
let loot2 = Loot(item: Sword())

如果您想以 ArmorSword 的形式访问项目,我建议在扩展中添加计算属性。最好将它们添加到扩展中,因为这不是 class 的核心功能的一部分,如果您创建另一种类型的 Item,如 Shield,这也是一个更好的设计,然后您可以在扩展中为其添加一个计算 属性,而无需修改主 class.

extension Loot {
    var armor: Armor? {
        get {
            guard let armor = item as? Armor else {return nil}
            return armor
        }
    }

    var sword: Sword? {
        get {
            guard let sword = item as? Sword else {return nil}
            return sword
        }
    }
}

然后您可以将它们作为可选对象访问

if let armor = loot1.armor {
    //do armor stuff
}