城镇结构:
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 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")
}
}
}
Zombie class:
class Zombie: Monster {
var walksWithLimp = true
final override func terrorizeTown() {
if town?.population > 0 {
town?.changePopulation(by: -10)
}
super.terrorizeTown()
}
}
我在town?.population
上收到编译错误,说明'可选的Int未解包的值...'。我没有声明population
是可选的,如果我将其更改为town?.population?
,则表示填充是非可选的Int。这两个错误互相矛盾,发生了什么?
答案 0 :(得分:2)
考虑以下示例:
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
的访问权限如果bar
不是.some(...)
,则会在foo
中包含nil
的值,否则为nil
。即,这样的查询(甚至是作为`bar的非可选属性)将产生一个可选的:
let optBar = foo?.bar // this is now an optional (Optional<Int>)
反映可以在
nil
上调用可选链接的事实 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?.bar ?? -1)
为-1
,foo
会产生nil
(随后false
会产生-1 > 0
),或者如果bar
不是Int
,则会产生foo
(作为非可选具体nil
)的值。
我们还可以有条件地使用map
method of Optional
(foo
不是nil
)来测试比较,如果foo
是nil
,在从false
调用返回时使用nil
合并运算符将map
作为默认值提供。
if foo.map({ $0.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({ $0.population > 0 }) ?? false {
town?.changePopulation(by: -10)
}
答案 1 :(得分:0)
表达式返回一个可选的componentDidMount
,但您仍在使用非可选语法对其进行测试。您需要使用Int
。
if let
等
可选链不会删除可选项。它只是级联它,以便链中的任何零都会导致最后弹出一个零。但结果仍然是可选的。
答案 2 :(得分:0)
因为城镇?。人口仍然是国家?,你无法比较国际?使用Int,除非你从Int获得Int?
所以代码可能是
if let town = town, town.population > 0 {
town.changePopulation(by: -10)
}
super.terrorizeTown()
答案 3 :(得分:0)
您必须初始化您构建Town的实例,否则它总是返回nil。所以我看到你的代码,镇?总是回到零。