Получить первое значение, которое не равно nil, в модели, полной пользовательских объектов - PullRequest
0 голосов
/ 14 марта 2020

Итак, у меня есть эта модель:

public class Loot {

    let sword: Sword?
    let armor: Armor?

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

Все эти атрибуты наследуются от Item класса.

В этой модели у меня всегда будет только 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
        }
}

Я могу получить первый объект, который не ноль, и база Item для него. распечатав это в приглашении с po loots.items, я действительно вижу, что это Armor объект. Но это все еще объект Item, поэтому я не могу получить атрибуты брони.

1 Ответ

2 голосов
/ 14 марта 2020

Вместо того, чтобы хранить два свойства, для которых установлено только одно, вы можете иметь обобщенный класс c с одним обязательным свойством. Таким образом, вам не нужно проверять, что установлено или не установлено

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

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

Пример

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

Если вы хотите получить доступ к элементу как Armor или Sword Я бы предложил добавить вычисляемые свойства в расширение. Лучше добавить их в расширение, так как это не является частью основной функциональности класса, и это также лучший дизайн, если вы создадите другой тип Item, такой как Shield, тогда вы можете добавить для него вычисляемое свойство в расширении без необходимости изменения основного класса.

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
}
...