当前位置: 首页 > 面试题库 >

通用函数在Swift中采用类型名称

谷梁鸣
2023-03-14
问题内容

在C#中,可以通过指定类型来调用泛型方法:

public T f<T>()
{
   return something as T
}

var x = f<string>()

Swift不允许您在调用通用方法时对它进行专门化处理。编译器希望依靠类型推断,因此这是不可能的:

func f<T>() -> T? {
    return something as T?
}

let x = f<String>() // not allowed in Swift

我需要的是一种使用泛型将类型传递给函数并返回该类型对象的方法

这可行,但是不适合我想做的事:

let x = f() as String?

编辑(澄清)

我可能不太清楚问题的实质,这全都是关于调用返回给定类型(任何类型)的函数的简单语法。

举一个简单的例子,假设您有一个Any数组,并创建了一个返回给定类型的第一个元素的函数:

// returns the first element in the array of that type
func findFirst<T>(array: [Any]) -> T? {
    return array.filter() { $0 is T }.first as? T
}

您可以这样调用此函数:

let array = [something,something,something,...]

let x = findFirst(array) as String?

这很简单,但是如果返回的类型是带有方法的某种协议,而您想在返回的对象上调用该方法,该怎么办:

(findFirst(array) as MyProtocol?)?.SomeMethodInMyProtocol()
(findFirst(array) as OtherProtocol?)?.SomeMethodInOtherProtocol()

该语法很尴尬。在C#(与Swift一样强大的类型)中,您可以执行以下操作:

findFirst<MyProtocol>(array).SomeMethodInMyProtocol();

可悲的是,这在Swift中是不可能的。

因此,问题是: 有没有一种方法可以使用更简洁(不太尴尬)的语法来完成此任务。


问题答案:

不幸的是,您不能显式定义泛型函数的类型(通过使用其<...>语法)。但是,您 可以 提供泛型元类型(T.Type)作为函数的 参数,以允许Swift推断函数的泛型,如Roman所说。

对于您的特定示例,您将希望函数看起来像这样:

func findFirst<T>(in array: [Any], ofType _: T.Type) -> T? {
  return array.lazy.compactMap { $0 as? T }.first
}

在这里,我们compactMap(_:)用来获取已成功转换为的元素序列T,然后first获取该序列的第一个元素。我们也正在使用,lazy以便我们可以在找到第一个元素后停止评估元素。

用法示例:

protocol SomeProtocol {
  func doSomething()
}

protocol AnotherProtocol {
  func somethingElse()
}

extension String : SomeProtocol {
  func doSomething() {
    print("success:", self)
  }
}

let a: [Any] = [5, "str", 6.7]

// Outputs "success: str", as the second element is castable to SomeProtocol.
findFirst(in: a, ofType: SomeProtocol.self)?.doSomething()

// Doesn't output anything, as none of the elements conform to AnotherProtocol.
findFirst(in: a, ofType: AnotherProtocol.self)?.somethingElse()

请注意,您必须使用.self来引用特定类型的元类型(在这种情况下为SomeProtocol)。也许不如您想要的语法那么精巧,但是我认为它与您将要获得的一样好。

尽管在这种情况下值得注意的是,最好将函数放在扩展中Sequence

extension Sequence {
  func first<T>(ofType _: T.Type) -> T? {
    // Unfortunately we can't easily use lazy.compactMap { $0 as? T }.first
    // here, as LazyMapSequence doesn't have a 'first' property (we'd have to
    // get the iterator and call next(), but at that point we might as well
    // do a for loop)
    for element in self {
      if let element = element as? T {
        return element
      }
    }
    return nil
  }
}

let a: [Any] = [5, "str", 6.7]
print(a.first(ofType: String.self) as Any) // Optional("str")


 类似资料:
  • 问题内容: 我想让一个函数在Swift中接受任何数字(Int,Float,Double,…) 不使用NSNumber 问题答案: 更新: 以下答案原则上仍然适用,但是Swift 4完成了数字协议的重新设计,因此通常不需要添加自己的数字协议。在构建自己的系统之前,请查看标准库的数字协议。 在Swift中,这实际上是不可能的。为此,您需要创建一个新协议,并使用您将在泛型函数中使用的任何方法和运算符进行

  • 问题内容: 在Swift中,调用第一个参数时会使用参数名称。为什么不使用名字? 使用Swift手册的变体; 这会起作用; 但这给了我“调用中的外部参数标签’amount’” 是否有这个原因,或者这是“按其原样”的事物之一? 问题答案: 这是遵循Objective-C习惯的惯例,第一个参数的名称与方法名称结合在一起。这是一个例子: 您可以像这样调用方法: 通过将参数的名称合并到方法的名称中,可以使阅

  • 问题内容: 使用泛型时,我在Java中有一个小问题。我有一堂课: 在方法中,我需要获取类型名称。有没有办法找到字符串使用? (如果创建了,我希望能够做到这一点- 我必须使用通用性,因为我的方法之一必须返回)。 这似乎很容易,但是我不知道如何去做。 问题答案: 由于 类型擦除, 您通常无法执行此操作-的实例不 知道 的类型。如果需要,一种方法是使用类型文字: 然后: 这很丑陋,但这就是类型擦除的作用

  • 问题内容: 我正在尝试创建一个字典变量,其值是两种类型之一。我的尝试的一个例子应该使这一点更清楚: 这引发了仅语法功能类型可以通用的编译器错误。我想知道是否有可能,我只是不知道正确的语法? 问题答案: 为此所需的工具是带有关联数据的枚举。 这样可以捕获“一个浮标或布尔对象”,并提供更好的文档记录和类型安全性。 要卸载数据,请使用switch语句: 使用switch语句可确保覆盖所有可能的类型,并防

  • 本文向大家介绍Swift语言函数类型,包括了Swift语言函数类型的使用技巧和注意事项,需要的朋友参考一下 示例 每个函数都有其自己的函数类型,该函数类型由参数类型和函数本身的返回类型组成。例如以下功能: 具有以下功能类型: 因此,函数类型可用作嵌套函数的参数类型或返回类型。

  • 假设我在Swift中定义了一个泛型类,类似于以下内容: (我知道数组有一个稍微好一点的实现,这只是一个例子。) 在Swift中,我现在可以非常容易地使用这个类: 在Xcode 7中,我们现在在Objective-C中拥有泛型,所以我假设我可以在Objective-C中使用这个类: 然而,MyArray从未添加到我的<code>项目Swift中。h文件。即使我将其更改为从NSObject继承,它仍然