城镇结构:
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")
}
}
}
僵尸类:
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?
,它表示 population 是一个非可选 Int。这两个错误相互矛盾,这是怎么回事?
最佳答案
可选链接,即使在查询非可选方法和属性时,也会产生一个可选的结果
考虑以下示例:
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查询对 foo
的 bar
的访问,这将为我们提供包含在 .some(...)< 中的
如果 bar
的值foo
不是 nil
,否则为 nil
。也就是说,这样的查询(甚至是非可选属性如 `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
block ,给出以下条件:
foo
不是nil
,并且- 如果是,
bar
大于0
然后您首先需要以某种方式实现(可能存在的)bar
的具体值,然后再将其与 0
进行比较。
你可以这样做,例如组合的可选绑定(bind)和 bool 条件 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
code>(随后将导致 -1 > 0
的 false
),或导致 bar
的值(作为非可选具体的 Int
),以防 foo
不是 nil
。
我们还可以利用 map
method of Optional
有条件地(foo
不是 nil
)测试比较,如果 foo
是 nil
,则提供 false
作为默认值,在调用 map
时使用 nil
合并运算符。
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)
}
关于swift - 可选结构的非可选属性显示为可选,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41503579/