我有这段代码
class MyObject<T> {
func start(_ value: T?) {
if let value = value {
doSomething(value)
}
}
func doSomething(_ value: T) {
print(value)
}
}
MyObject<String>().start("some")
// prints "some"
MyObject<String?>().start(nil)
// doesn't print anything
我需要为传递到-doSomething:
的每个有效值调用-start:
。并且当T == String?
时,nil
是有效值。
我是否需要在-start
的扩展名中写上MyObject
类型的两个版本的T
?以及如何做到?
答案 0 :(得分:2)
您可以使您的start
函数采用非可选的T
,而总是调用doSomething
而不是尝试先对其进行拆包。仅当start(nil)
本身是可选类型时,这才允许您调用T
:
class MyObject<T> {
func start(_ value: T) {
doSomething(value)
}
func doSomething(_ value: T) {
print(value)
}
}
MyObject<String>().start("some")
// prints "some"
MyObject<String?>().start(nil)
// prints "nil"
如果您想将参数保留为start
作为可选参数,那么您的原始代码将可以正常使用,但是您需要在第二个示例中更改传递值的方式。
由于T
为String?
,因此您方法中的参数的类型为String??
,并且传递nil String??
的方式与通过String?
传递参数的方式不同。恰好包含nil
。
如果您将其称为:
MyObject<String?>().start(.some(nil))
或
let string: String? = nil
MyObject<String?>().start(string)
然后它将显示“ nil”
答案 1 :(得分:0)
由于let value = value在第二个输入中失败,因此您需要单独处理这种情况。
func start(_ value: T?) {
if let value = value {
doSomething(value)
}
else
{
print("nil input")
}
}
答案 2 :(得分:0)
如果值是nil,则当展开时,该值将不会输入if语句中。相反,您可以执行以下操作:
class MyObject<T> {
func start(_ value: T?) {
if let value = value {
doSomething(value)
} else {
print("nil")
}
}
func doSomething(_ value: T) {
print(value)
}
}
答案 3 :(得分:0)
Swift中的可选只是一个通用枚举,有两种情况:
enum Optional<T> {
case some(T)
case none
}
例如String?
与Optional<String>
是同一件事。
如果您声明MyObject<String?>
基本上是在创建此MyObject<Optional<String>>
,那么您的具体start
方法将是
func start(_ value: Optional<Optional<String>>) { ... }
这意味着,如果您像start(nil)
那样调用它,则整个对象当然为nil,而if let
将失败。
但是,您可以通过这种方式调用该函数
MyObject<String?>().start(Optional.some(Optional.none))
MyObject<String?>().start(.some(.none)) // -> shorter version with type inference
基本上,现在存在外部可选对象,并且可展开,但内部可选对象为nil
。
但是我仍然不明白为什么你需要做类似的事情