[英]swift optional generic type and nested optional unwrapping
I've got this piece of code我有这段代码
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
I need doSomething()
to be called for every valid value passed to start()
.我需要为传递给
start()
每个有效值调用doSomething()
start()
。 And when T
is already an optional type like String?
当
T
已经是像String?
这样的可选类型时String?
, then nil
is a valid value. ,则
nil
是有效值。
Do I need to write two versions of start()
in extensions of MyObject
with conditions on the type of T
?我是否需要在
MyObject
扩展中编写两个版本的start()
并带有T
类型的条件? And how to do it?以及怎么做?
You can make your start
function take a non-optional T
and just always call doSomething
instead of trying to unwrap it first.你可以让你的
start
函数接受一个非可选的T
并且总是调用doSomething
而不是首先尝试解包它。 This would only allow you to call start(nil)
if T
itself was an optional type:如果
T
本身是可选类型,这将只允许您调用start(nil)
:
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"
If you want to leave the parameter to start
as optional then your original code will actually work, but you need to change the way you are passing your value in your second example.如果你想离开参数来
start
可选那么你原来的代码将实际工作,但你需要改变你传递你的价值在你的第二个例子的方式。
Since T
is String?
由于
T
是String?
, the parameter in your method is of type String??
, 你方法中的参数是
String??
and passing a nil String??
并传递一个零
String??
is different then passing one with a String?
与传递一个
String?
that happens to contain nil
.恰好包含
nil
。
If you call it as:如果你称之为:
MyObject<String?>().start(.some(nil))
or或者
let string: String? = nil
MyObject<String?>().start(string)
Then it will print "nil"然后它会打印“nil”
Since let value = value fails with the second input you need to handle that case separately.由于 let value = value 在第二个输入时失败,您需要单独处理这种情况。
func start(_ value: T?) {
if let value = value {
doSomething(value)
}
else
{
print("nil input")
}
}
In case value is nil, when you unwrap the value will not enter in the if statement.如果值为 nil,则解包时该值将不会进入 if 语句。 Instead, you can do this:
相反,您可以这样做:
class MyObject<T> {
func start(_ value: T?) {
if let value = value {
doSomething(value)
} else {
print("nil")
}
}
func doSomething(_ value: T) {
print(value)
}
}
Optional in Swift is just a generic enum that have two cases: Swift 中的 Optional 只是一个通用枚举,它有两种情况:
enum Optional<T> {
case some(T)
case none
}
For example String?
例如
String?
is the same thing of Optional<String>
.与
Optional<String>
。
If you declare MyObject<String?>
basically you're creating this MyObject<Optional<String>>
, so your concrete start
method will be如果你声明
MyObject<String?>
基本上你正在创建这个MyObject<Optional<String>>
,所以你的具体start
方法将是
func start(_ value: Optional<Optional<String>>) { ... }
This means that if you call it like start(nil)
, the whole object will be of course nil and the if let
will fail.这意味着如果你像
start(nil)
一样调用它,整个对象当然会是 nil 并且if let
会失败。 You can however call that function in this way但是,您可以通过这种方式调用该函数
MyObject<String?>().start(Optional.some(Optional.none))
MyObject<String?>().start(.some(.none)) // -> shorter version with type inference
Basically now the outer optional exists and the unwrap works, but the inner one is nil
.基本上现在外部的 optional 存在并且 unwrap 工作,但内部的是
nil
。
However I still can't understand why would you need to do something like that但是我仍然不明白为什么你需要做这样的事情
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.