将方法或类约束为仅接受选项



我需要约束API,这样用户只能用显式可选的类型来调用它。我怎样才能做到这一点?

class Foo<T> {
let value: T?
init(_ value: T?) {
self.value = value
}
}
let optionalValue: Bool? = true
Foo(optionalValue) // Should work
let nonOptionalValue: Bool = true
Foo(nonOptionalValue) // Should fail, ideally at compile time
Foo(true) // Should work or acceptable to replace it with 
Foo(.some(true))

问题是,如果在需要Optional的地方传递非Optional,则不会拒绝该非Optional;相反,它被隐式地包装在Optional中。这就是为什么这行代码是合法的:

let optionalValue: Bool? = true

出于同样的原因,这行代码是合法的:

let nonOptionalValue: Bool = true
Foo(nonOptionalValue) // even though Foo's parameter is typed as Optional

无法关闭此功能。它已融入语言。事实上,正如第一个例子所表明的那样,你自己已经开始依赖它了!因此,正是出于这个原因,您永远无法阻止非可选项在此处传递。这就是我们为隐式可选包装的便利性所付出的代价。

一个选项可以是用inout属性声明init。

init(_ value: inout T?) {
self.value = value
}

下面一行给出编译器错误";Inout参数可以设置为类型不是"Bool"的值;使用声明为类型"Bool?"的值取而代之的是";

Foo(&nonOptionalValue) // Should fail, ideally at compile time

限制条件:

  1. Foo类的用户可能不想通过引用传递
  2. 用户将无法编写Foo(true(

但是,可以通过在调用init之前创建一个本地var来解决这些问题。

最新更新