在此下标代码中:
{
"_id" : ObjectId("5be7fc909625592852d422b4"),
"time" : ISODate("2018-11-11T09:55:28.704Z"),
"receiver" : ObjectId("5be5d727d3f24e06b144e229"),
"createdAt" : ISODate("2018-11-11T09:55:28.718Z"),
"updatedAt" : ISODate("2018-11-11T09:55:28.718Z"),
}
{
"_id" : ObjectId("5be807902b789e5c3c05dc5e"),
"time" : ISODate("2018-11-11T10:42:24.410Z"),
"receiver" : ObjectId("5be5d727d3f24e06b144e229"),
"createdAt" : ISODate("2018-10-09T18:30:00Z"),
"updatedAt" : ISODate("2018-10-09T18:30:00Z"),
}
为什么extension Array where Element: Foo {
subscript(key: String) -> Any? {
get {
return self.first(where: { $0.key == key })
}
set {
self.append(Element(key: key, value: newValue))
}
}
}
class Foo {
var key: String
var value: Any?
// Why "required"?
required init(key: String, value: Any?) {
self.key = key
self.value = value
}
}
必须位于Foo.init前面?
如果删除它,则会出现此错误:
required
答案 0 :(得分:3)
您需要标记初始化器required
,因为您是从通用扩展名中使用它的,该扩展名适用于从Foo
继承的所有类型(包括Foo
本身)。但是,如果未将初始化程序标记为required
,则Foo
子类可能无法继承该初始化程序,以防它们定义了至少一个指定的初始化程序,如Automatic Initializer Inheritance中所述。
因此,除非您标记了init(key: String, value: Any?)
Foo
的{{1}}初始化程序,否则您的通用Array扩展程序无法保证扩展程序适用的所有类型都存在该扩展程序中调用的初始化程序方法
如果您只想将扩展名应用于required
类,而又不想将其应用于子类,则可以使用Foo
,在这种情况下,您无需标记初始化程序是必需的,因为保证extension Array where Element == Foo {...
类型具有该初始化程序。
答案 1 :(得分:3)
required
关键字意味着继承的类必须提供该方法的实现。
extension Array where Element: Foo
意味着扩展应该适用于所有继承自Foo
的类,因此所有required
都可以实现init(key: String, value: Any?)
。
因此,必须添加required
关键字以确保这一点。
如果它是extension Array where Element == Foo
,则不需要required
,因为对于类型Foo
,定义了init
并带有适当的签名,并且不需要任何签名检查。
进行Foo
的决赛(final class Foo {}
)也将消除required
中的需求。