可选结构的非可选 属性 显示为可选
Non-optional property of optional struct being shown as optional
城镇结构:
struct Town {
var population: Int = 5_422
var numberOfStoplights: Int = 4
func printDescription() {
print("The town has \(population) people and \(numberOfStoplights) stoplights")
}
mutating func changePopulation(by amount: Int) {
population += amount
}
}
怪物class:
class Monster {
var town: Town?
var name = "Monster"
func terrorizeTown() {
if town != nil {
print("\(name) is terrorizing a town")
} else {
print("\(name) hasn't found a town to terrorize yet")
}
}
}
僵尸class:
class Zombie: Monster {
var walksWithLimp = true
final override func terrorizeTown() {
if town?.population > 0 {
town?.changePopulation(by: -10)
}
super.terrorizeTown()
}
}
我在 town?.population
上遇到编译器错误 'value of optional Int not unwrapped...'。我还没有声明 population
是可选的,如果我将其更改为 town?.population?
它表示 population 是一个非可选的 Int。这两个错误相互矛盾,这是怎么回事?
表达式 returns 是可选的 Int
但您仍在使用非可选语法测试它。您需要使用 if let
.
if let pop = town?.population {
if pop > 0
等等
可选链不删除可选性。它只是将其级联,以便链中的任何 nil 都会导致 nil 在末尾弹出。但结果仍然是可选的。
因为 town?.population 还是 Int?, 你不能比较 Int?用 Int 除非你从 Int 得到 Int?
所以代码可以是
if let town = town, town.population > 0 {
town.changePopulation(by: -10)
}
super.terrorizeTown()
你必须初始化你的城镇结构实例,否则它总是return nil。所以我看到你的代码了,Town?总是 return 零。
可选链接,即使在查询非可选方法和属性时,也会产生一个可选的结果
考虑以下示例:
struct Foo {
let bar: Int // not: not an optional
init(_ bar: Int) { self.bar = bar }
}
let foo: Foo? = Foo(42) // 'foo' is an optional
如果我们不是特别对 foo
感兴趣,而是特别对其成员 bar
感兴趣,我们可以使用 optional chaining 查询对 bar
的访问 foo
,如果 foo
不是 nil
,这将为我们提供包含在 .some(...)
中的 bar
的值,否则为 nil
。也就是说,这样的查询(即使是非可选的 属性 as `bar)也会产生一个可选的:
let optBar = foo?.bar // this is now an optional (Optional<Int>)
To reflect the fact that optional chaining can be called on a nil
value, the result of an optional chaining call is always an optional
value, even if the property, method, or subscript you are querying
returns a nonoptional value.
在我们继续之前,我们还注意到在 Swift 3 中我们可能不再比较 Comparable
运算符的可选操作数,如以下接受和实施的 Swift 演化所述建议:
因此,如果您想有条件地进入 if
块,请给出以下条件:
foo
不是 nil
,并且
- 如果是,
bar
大于 0
然后您首先需要以某种方式实现(可能存在的)bar
的具体值,然后再将其与 0
进行比较。
您可以这样做,例如组合的可选绑定和布尔条件 if
语句:
if let nonOptionalBar = foo?.bar, nonOptionalBar > 0 {
print("'foo' is not nil and its 'bar' member is larger than 0")
} // prints "'foo' is not nil and its 'bar' member is larger than 0"
如果您不打算使用值 bar
,但是(并且只想减少它的数量),您可以使用 nil
coalescing operator 来构造条件 if
语句将失败,因为 foo
是 nil
或其成员 bar
不大于 0:
if (foo?.bar ?? -1) > 0 {
print("'foo' is not nil and its 'bar' member is larger than 0")
}
在这里,如果 foo
是 nil
,(foo?.bar ?? -1)
将导致 -1
(随后将导致 false
for -1 > 0
) ,或者在 foo
不是 nil
.
的情况下导致 bar
的值(作为非可选的具体 Int
)
我们也可以利用 map
method of Optional
有条件地(即 foo
不是 nil
)测试比较,如果 foo
是 nil
,在调用 map
.
的 return 上使用 nil
合并运算符提供 false
作为默认值
if foo.map({ [=14=].bar > 0 }) ?? false {
print("'foo' is not nil and its 'bar' member is larger than 0")
}
适用于您的示例的三个备选方案:
if let population = town?.population, population > 0 {
town?.changePopulation(by: -10)
}
if (town?.population ?? -1) > 0 {
town?.changePopulation(by: -10)
}
if town.map({ [=15=].population > 0 }) ?? false {
town?.changePopulation(by: -10)
}
城镇结构:
struct Town {
var population: Int = 5_422
var numberOfStoplights: Int = 4
func printDescription() {
print("The town has \(population) people and \(numberOfStoplights) stoplights")
}
mutating func changePopulation(by amount: Int) {
population += amount
}
}
怪物class:
class Monster {
var town: Town?
var name = "Monster"
func terrorizeTown() {
if town != nil {
print("\(name) is terrorizing a town")
} else {
print("\(name) hasn't found a town to terrorize yet")
}
}
}
僵尸class:
class Zombie: Monster {
var walksWithLimp = true
final override func terrorizeTown() {
if town?.population > 0 {
town?.changePopulation(by: -10)
}
super.terrorizeTown()
}
}
我在 town?.population
上遇到编译器错误 'value of optional Int not unwrapped...'。我还没有声明 population
是可选的,如果我将其更改为 town?.population?
它表示 population 是一个非可选的 Int。这两个错误相互矛盾,这是怎么回事?
表达式 returns 是可选的 Int
但您仍在使用非可选语法测试它。您需要使用 if let
.
if let pop = town?.population {
if pop > 0
等等
可选链不删除可选性。它只是将其级联,以便链中的任何 nil 都会导致 nil 在末尾弹出。但结果仍然是可选的。
因为 town?.population 还是 Int?, 你不能比较 Int?用 Int 除非你从 Int 得到 Int?
所以代码可以是
if let town = town, town.population > 0 {
town.changePopulation(by: -10)
}
super.terrorizeTown()
你必须初始化你的城镇结构实例,否则它总是return nil。所以我看到你的代码了,Town?总是 return 零。
可选链接,即使在查询非可选方法和属性时,也会产生一个可选的结果
考虑以下示例:
struct Foo {
let bar: Int // not: not an optional
init(_ bar: Int) { self.bar = bar }
}
let foo: Foo? = Foo(42) // 'foo' is an optional
如果我们不是特别对 foo
感兴趣,而是特别对其成员 bar
感兴趣,我们可以使用 optional chaining 查询对 bar
的访问 foo
,如果 foo
不是 nil
,这将为我们提供包含在 .some(...)
中的 bar
的值,否则为 nil
。也就是说,这样的查询(即使是非可选的 属性 as `bar)也会产生一个可选的:
let optBar = foo?.bar // this is now an optional (Optional<Int>)
To reflect the fact that optional chaining can be called on a
nil
value, the result of an optional chaining call is always an optional value, even if the property, method, or subscript you are querying returns a nonoptional value.
在我们继续之前,我们还注意到在 Swift 3 中我们可能不再比较 Comparable
运算符的可选操作数,如以下接受和实施的 Swift 演化所述建议:
因此,如果您想有条件地进入 if
块,请给出以下条件:
foo
不是nil
,并且- 如果是,
bar
大于0
然后您首先需要以某种方式实现(可能存在的)bar
的具体值,然后再将其与 0
进行比较。
您可以这样做,例如组合的可选绑定和布尔条件 if
语句:
if let nonOptionalBar = foo?.bar, nonOptionalBar > 0 {
print("'foo' is not nil and its 'bar' member is larger than 0")
} // prints "'foo' is not nil and its 'bar' member is larger than 0"
如果您不打算使用值 bar
,但是(并且只想减少它的数量),您可以使用 nil
coalescing operator 来构造条件 if
语句将失败,因为 foo
是 nil
或其成员 bar
不大于 0:
if (foo?.bar ?? -1) > 0 {
print("'foo' is not nil and its 'bar' member is larger than 0")
}
在这里,如果 foo
是 nil
,(foo?.bar ?? -1)
将导致 -1
(随后将导致 false
for -1 > 0
) ,或者在 foo
不是 nil
.
bar
的值(作为非可选的具体 Int
)
我们也可以利用 map
method of Optional
有条件地(即 foo
不是 nil
)测试比较,如果 foo
是 nil
,在调用 map
.
nil
合并运算符提供 false
作为默认值
if foo.map({ [=14=].bar > 0 }) ?? false {
print("'foo' is not nil and its 'bar' member is larger than 0")
}
适用于您的示例的三个备选方案:
if let population = town?.population, population > 0 {
town?.changePopulation(by: -10)
}
if (town?.population ?? -1) > 0 {
town?.changePopulation(by: -10)
}
if town.map({ [=15=].population > 0 }) ?? false {
town?.changePopulation(by: -10)
}