generics - 如何确定泛型在 Swift 中是否是可选的?

标签 generics swift option-type

我想用一个函数扩展一个数组,该函数将返回数组中所有非零项的计数。理想情况下,这将适用于任何可选或非可选类型的数组。我尝试了各种编译失败、Xcode 崩溃或两者兼而有之的尝试。我本以为它看起来像这样:

extension Array {
    func realCount() -> Int {
        var cnt = 0
        for value in self {
            if value != nil {
                cnt++
            }
        }

        return cnt
    }
}

这里 Swift 提示 T 不能转换为 UInt8。或者有时 MirrorDisposition 或其他随机类。

假设这是可能的,有什么窍门?

编辑:从 Xcode 6 beta 5 开始,它现在可以编译但没有给出预期的结果。 if value != nil 每次都计算为 true。

最佳答案

您不能将任意值与 nil 进行比较(编辑:但请参阅下面 Sulthan 的评论;可能我们应该能够将任意值与 nil;本段的其余部分在今天可能是正确的,但只是由于编译器错误)。虽然 Optional 应用了一些语法糖,但它实际上只是一个枚举,而 nil 只是 Optional.None。您希望一种类型有一种行为(可选),而另一种行为适用于所有其他类型。 Swift 通过泛型实现这一点,而不是在扩展中。你必须把它变成一个函数:

func realCount<T>(x: [T?]) -> Int {
  return countElements(filter(x, { $0.getLogicValue() } ) )
}

func realCount<T>(x: [T]) -> Int {
  return countElements(x)
}

let l = [1,2,3]
let lop:[Int?] = [1, nil, 2]

let countL = realCount(l) // 3
let countLop = realCount(lop) // 2

这种方法更加灵活。 Optional 只是您希望以这种方式进行 flatMap 的众多类型之一(例如,您可以使用相同的技术来处理 Result )。


编辑:您可以通过为您认为“真实”的事物创建协议(protocol)来更进一步。这样你就不必将它限制在 Optionals 中。例如:

protocol Realizable {
  func isReal() -> Bool
}

extension Optional: Realizable {
  func isReal() -> Bool { return self.getLogicValue() }
}

func countReal<S:Collection>(x: S) -> S.IndexType.DistanceType {
  return countElements(x)
}

func countReal<S:Collection where S.GeneratorType.Element:Realizable>(x: S) -> Int {
  return countElements(filter(x, {$0.isReal()}))
}

这就是说,如果我传递一组“可实现”的东西,然后根据它们的规则过滤它们。否则,只需计算它们。虽然我可能不会真正使用这个函数(它看起来很特殊),但这个概念很有用。以后的调用者可以添加新的“可实现”类型,而无需修改您的任何代码(甚至不知道它们是如何实现的)。这展示了如何为未实现您的协议(protocol)的事物设置默认行为。

顺便说一句,我在这里使用 Collections 只是因为它们更容易计数(而且我对返回类型有点马虎;注意一个是 DistanceType,另一个是 Int)。在基于通用集合的函数上获得正确的类型仍然有点棘手(并且经常使编译器崩溃)。我怀疑这一切都会在下一个测试版中得到改善。

关于generics - 如何确定泛型在 Swift 中是否是可选的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25064644/

相关文章:

ios - 最小化 iOS 应用程序大小

swift - 如何根据远程服务器的响应以编程方式从另一个 View Controller 调用 View Controller

ios - 如何在swift中获取类型字典数组的键

swift - 我应该将字符串设置为 Nil 还是 Empty?

java - 以函数式风格将 Optional 转换为 boolean

java - 如何使用反射来识别java方法是否是通用的?

java - 具有通配符类型的生产者方法

C#:如何在 xml 注释中引用 default(T) 和构造函数

swift - 我得到了我不能得到的可选值。 swift 3.2

java - 检查枚举类型是否包含具有给定名称的常量