Swift where 条件检查属性是否已实现

2024-04-13

我刚刚找到了另一种在 Swift 中充分利用协议和协议扩展的方法,即扩展可选协议来添加函数,以便我可以提供默认值。

我在这里写了一篇关于此的博客文章:https://janthielemann.de/random-stuff/providing-default-values-可选-string-empty-可选-string-swift-3-1/ https://janthielemann.de/random-stuff/providing-default-values-optional-string-empty-optional-string-swift-3-1/

这篇文章的要点是,我需要一种干净、简单的方法来为可选字符串(nil 或空)提供默认值。为此,我创建了一个 Emptyable 协议并扩展了可选协议,如下所示:

protocol Emptyable {
    var isEmpty: Bool { get }
}

extension Optional where Wrapped: Emptyable {
    func orWhenNilOrEmpty<T: Emptyable>(_ defaultValue: T) -> T {
        switch(self) {
        case .none:
            return defaultValue
        case .some(let value) where value.isEmpty:
            return defaultValue
        case .some(let value):
            return value as! T
        }
    }
}

extension String: Emptyable {}

现在的问题是:有没有一种方法可以摆脱 Emptyable 协议,而是有条件检查属性或函数是否由泛型类型实现,以便我自动为每个具有以下属性的类型获取 orWhenNilOrEmpty() :isEmpty?

UPDATE

正如 Paulo 所建议的,T 泛型实际上是不需要的,我创建了一个操作符,以便更快地访问和更方便的使用(至少我是这么认为的。请随意纠正我,我总是很乐意学习新东西并提高自己) )。

我称之为“非空零合并”运算符(谁能想出更好的名字?我觉得我在命名事物方面很糟糕:/)。希望有一天它能帮助某人:

protocol Emptyable {
    var isEmpty: Bool { get }
}

infix operator ???: NilCoalescingPrecedence

extension Optional where Wrapped: Emptyable {
    func orWhenNilOrEmpty(_ defaultValue: Wrapped) -> Wrapped {
        switch(self) {
        case .none:
            return defaultValue
        case .some(let value) where value.isEmpty:
            return defaultValue
        case .some(let value):
            return value
        }
    }

    static func ???(left: Wrapped?, right: Wrapped) -> Wrapped {
        return left.orWhenNilOrEmpty(right)
    }
}

extension String: Emptyable {}

extension Array: Emptyable {}

extension MyStruct: Emptyable {
    let text: String
    let number: Int
    var isEmpty: Bool { return text.isEmpty && number == 0 }
    init(text: String, number: Int) {
        self.text = text
        self.number = number
    }
}

let mandatoryNotEmptyString = optionalOrEmptyString ??? "Default Value"
let mandatoryNotEmptyStruct = optionalOrEmptyStruct ??? MyStruct(name: "Hello World", number: 1)

不可以,如果不使用协议,您无法查询对象或值是否具有特定属性作为扩展的约束。这需要以目前 Swift 中尚未实现的方式进行反射。另外,一个isEmpty属性对于不同的类型可能有不同的含义,因此测试方法或属性而不是协议的存在可能会导致意外的行为。

你可以只写

if let unwrappedString = optionalString, !unwrappedString.isEmpty {
    // Do stuff
} else {
    // Use default value
}

不需要协议或扩展并且非常可读。

在今年秋天发布的 Swift 4 中,String将符合BidirectionalCollection https://github.com/apple/swift-evolution/blob/master/proposals/0163-string-revision-1.md,它继承自Collection. The Collection协议提供了一个isEmpty财产,所以你的扩展可以是

extension Optional where Wrapped: Collection {
     // ...
}

但即便如此,您也应该考虑在首先存储空字符串时将其设置为 nil,因为您现在有两种状态(nil 和empty),它们似乎代表完全相同的事物。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Swift where 条件检查属性是否已实现 的相关文章

随机推荐