【问题标题】:How to call a generic function with no parameter?如何调用没有参数的泛型函数?
【发布时间】:2016-07-30 00:21:47
【问题描述】:

给 Array 添加一个扩展,返回第一个 Int 或 String 很简单:

extension Array {
    func firstInt() -> Int? {
        return self.flatMap{$0 as? Int}.first
    }
    func firstString() -> String? {
        return self.flatMap{$0 as? String}.first
    }
}

let a1:[AnyObject?] = [nil, "abc", 3, 4]
let a2:[AnyObject?] = [nil, [3], [ "foo":"bar" ]]
print(a1.firstInt()) // Optional(3)
print(a2.firstInt()) // nil
print(a1.firstString()) // Optional("abc")
print(a2.firstString()) // nil

我可以定义一个通用版本,但我不知道如何调用它,因为它不带任何参数。没有参数,我无法指定类型!

extension Array {
    func firstValueOfType<T>() -> T? {
        return self.flatMap{$0 as? T}.first
    }
}
// I can't figure out how to call this method!

我可以通过添加一个虚拟参数来解决它,但这很难看。

extension Array {
    func firstValueLike<T>(_:T) -> T? {
        return self.flatMap{$0 as? T}.first
    }
}

let a1:[AnyObject?] = [nil, "abc", 3, 4]
print(a1.firstValueLike(1)) // Optional(3)
print(a1.firstValueLike("")) // Optional("abc")

如果有人能告诉我如何调用 firstValueOfType 函数(或干净地定义通用函数的替代方法),我将不胜感激。

附加信息

“不能显式特化泛型函数”是类似的,但我的问题有点复杂,因为可选。

我从 OOPer 那里得到了一个很好的答案,它甚至包括更好的实现,它使用了lazy.filter,而不是 flatMap。

extension Array {
    func firstValueOfType<T>() -> T? {
        return self.lazy.filter {$0 is T}.first as? T
    }
}

let a1:[AnyObject?] = [nil, "abc", 3, 4]
print(a1.firstValueOfType() as Int?) // Optional(3)
print(a1.firstValueOfType() as String?) // Optional("abc")

非常感谢您的快速支持!

【问题讨论】:

标签: swift generics


【解决方案1】:

一种方法是将结果分配给具有显式类型的变量。

let i: Int? = a1.firstValueOfType()
print(i) // Optional(3)
let s: String? = a1.firstValueOfType()
print(s) // Optional("abc")

另一个正在使用as

print(a1.firstValueOfType() as Int?) // Optional(3)
print(a1.firstValueOfType() as String?) // Optional("abc")

【讨论】:

  • 我喜欢这个答案。谢谢!
  • @LeoDabus,这不会迭代整个数组:self.lazy.filter{$0 is T}.first as? T
  • @LeoDabus,Playground 不是计算实际迭代次数的好地方。试试self.lazy.filter{print($0);return $0 is T}.first as? T,看看打印了多少行。
  • @LeoDabus,当然。也许应该在更合适的地方讨论。
【解决方案2】:

您可以使用T.Type 将类型作为参数传递,如下所示:

extension Array {
    func firstValue<T>(like type: T.Type) -> T? {
        return self.flatMap{$0 as? T}.first
    }
}

[1,2,3].firstValue(like: Int.self)

【讨论】:

  • 我有一个方法需要使用在该方法的包含类中定义的通用类型进行初始化。但我不需要任何其他参数。所以这绝对成功了。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-26
  • 1970-01-01
  • 1970-01-01
  • 2022-01-10
  • 2022-01-04
  • 2023-03-03
相关资源
最近更新 更多