swift - 我怎样才能编写一个函数,假设它是一个可选类型,那么它会在 swift 中解开通用属性?

标签 swift generics option-type

到目前为止,我只能使用全局函数来实现这一点。我不确定这是否可能,但我希望编写一个通用类的扩展,希望能实现同样的目标。

下面是它使用 ReactiveCocoa 中的 SignalProducer 类的工作全局函数,但对于任何泛型类,其原理应该是相同的。

func ignoreNilValues <Value,Error> (producer: SignalProducer<Value?,Error>) -> SignalProducer<Value, Error> {
   return producer.filter { return $0 != nil }.map { $0! }
}

更新:

我已经取得了进展,但仍然没有找到完整的解决方案

给定具有某些通用属性的任何类

class GenericClass<SomeType> {
    var someProperty: [SomeType] = []
}

如何编写一个扩展来过滤任何可选值并使用 Wrapped 类型返回该值?

以下内容将过滤任何 nil 值,但仍将其作为可选类型返回。

protocol AnOptional {
    var isNil: Bool {get}
}

extension Optional : AnOptional {
    var isNil: Bool {
        get {
            guard let hasValue = self.map({ (value: Wrapped) -> Bool in
                return true
            }) else {
                return true
            }

            return !hasValue
        }
    }
}

extension GenericClass where SomeType : AnOptional {
    func filterNilValuesOfSomeProperty() -> [SomeType] {
        return someProperty.filter({ (anOptional: AnOptional) -> Bool in
            return !anOptional.isNil
        })
    }
}

可以看出

let aClass = GenericClass<Int?>()

aClass.someProperty = [3,5,6,nil,4,3,6, nil]

let x = aClass.someProperty 
//x = [Some(3),Some(5),Some(6),nil,Some(4),Some(3),Some(6), nil]

let y = aClass.filterNilValuesOfSomeProperty()
//y = [Some(3),Some(5),Some(6),Some(4),Some(3),Some(6)]

是否可以编写一个返回包装类型的类扩展?在上面的示例中,它将是 [Int] 而不是 [Int?]

我重写了这个例子的全局函数解决方案。

func ignoreNilValues <Value> (aClass: GenericClass<Value?>) -> GenericClass<Value> {
    let aNewClass = GenericClass<Value>()

    aNewClass.someProperty = aClass.someProperty.filter({ (v: Value?) -> Bool in
        v != nil
    }).map { (oldValue: Value?) -> Value in
        return oldValue!
    }

    return aNewClass
}

let z = ignoreNilValues(aClass).someProperty
//z = [3, 5, 6, 4, 3, 6]

最佳答案

“技巧”是定义一个所有选项都遵循的协议(protocol) (这是来自Creating an extension to filter nils from an Array in Swift 稍作简化;这个想法可以追溯到 this Apple Forum Thread ):

protocol OptionalType {  
    typealias Wrapped 
    func intoOptional() -> Wrapped?  
}  

extension Optional : OptionalType {  
    func intoOptional() -> Wrapped? {  
        return self 
    }  
}  

您可以在您的情况下将其用作:

class GenericClass<SomeType> {
    var someProperty: [SomeType] = []
}

extension GenericClass where SomeType : OptionalType {
    func filterNilValuesOfSomeProperty() -> [SomeType.Wrapped] {
        return someProperty.flatMap { $0.intoOptional() }
    }
}

它使用 SequenceType 中的 flatMap() 方法:

extension SequenceType {
    /// Return an `Array` containing the non-nil results of mapping
    /// `transform` over `self`.
    ///
    /// - Complexity: O(*M* + *N*), where *M* is the length of `self`
    ///   and *N* is the length of the result.
    @warn_unused_result
    public func flatMap<T>(@noescape transform: (Self.Generator.Element) throws -> T?) rethrows -> [T]
}

示例:

let aClass = GenericClass<Int?>()
aClass.someProperty = [3,5,6,nil,4,3,6, nil]

let x = aClass.someProperty 
print(x) // [Optional(3), Optional(5), Optional(6), nil, Optional(4), Optional(3), Optional(6), nil]

let y = aClass.filterNilValuesOfSomeProperty()
print(y) // [3, 5, 6, 4, 3, 6]

Swift 3 及更高版本中,协议(protocol)必须定义为

protocol OptionalType {
    associatedtype Wrapped
    func intoOptional() -> Wrapped?
}

关于swift - 我怎样才能编写一个函数,假设它是一个可选类型,那么它会在 swift 中解开通用属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34563161/

相关文章:

ios - 函数运行时显示 UIView/UIImage/UITextView

ios - 有没有办法安排对 firebase 数据库的编辑?

ios - 如何在 Google MapView iOS 中设置固定标记位置

java - 实现除类签名之外的接口(interface)

swift - 隐式解包可选的可选绑定(bind)

ios - UIBezierPath 没有出现

scala - Scala 中的 A[B[C]] 类型,即嵌套类型构造函数

java - 泛型类继承

ios - 如何避免 Swift UIViewControllers 中的可选检查?

java - 缓存的 Optional<Boolean> 值