指定的(甚至是必需的)初始化器和便利初始化器之间的参数数量没有相关性。
便利初始化器只是那些需要将初始化转发到指定初始化器之一的初始化器。它有多少输入参数完全取决于实现和用例。它可能更多、更少或相等。
很难找到一个足够简单的例子来展示所有这些,但考虑一下这样的事情:
class HighlightedWordContainer {
let words: [String]
var highlightedWord: String
init(words: [String], highlighted: String) {
self.words = words
self.highlightedWord = highlighted
}
init(words: [String], highlightedIndex: Int) {
self.words = words
self.highlightedWord = words[highlightedIndex]
}
convenience init(singleWord: String) {
self.init(words: [singleWord], highlighted: singleWord)
}
convenience init(word1: String, word2: String, word3: String, highlighted: String) {
self.init(words: [word1, word2, word3], highlighted: highlighted)
}
convenience init(wordsSeparatedByWhitespace: String, highlightedIndex: Int) {
let words = wordsSeparatedByWhitespace.components(separatedBy: .whitespaces)
self.init(words: words, highlightedIndex: highlightedIndex)
}
convenience init?(descriptor: [String: Any], keys: [String], selectedKey: String) {
let words: [String] = keys.compactMap { descriptor[$0] as? String }
guard words.isEmpty == false else { return nil }
guard let selectedWord = descriptor[selectedKey] as? String else { return nil }
guard let selectedWordIndex = words.firstIndex(of: selectedWord) else { return nil }
self.init(words: words, highlightedIndex: selectedWordIndex)
}
}
在这里,我创建了一个带有 2 个指定初始化程序的类。这两个需要设置默认情况下尚未设置的所有属性。这意味着他们需要同时设置words 和highlightedWord。指定的初始化程序不能将调用委托给另一个指定的初始化程序,因此以下内容将不起作用:
init(words: [String], highlightedIndex: Int) {
self.init(words: words, highlighted: words[highlightedIndex])
}
并且所有便利初始化器都需要调用任何指定的初始化器,并且在调用指定的构造函数之前也可能不会直接设置或使用self 属性。所以:
convenience init(wordsSeparatedByWhitespace: String, highlightedIndex: Int) {
let words = wordsSeparatedByWhitespace.components(separatedBy: .whitespaces)
// print(highlightedWord) // NOT OK!
self.init(words: words, highlightedIndex: highlightedIndex)
print(highlightedWord)
}
我希望从示例中可以清楚地看出,便利初始化程序可以有更多、更少或相同数量的输入参数。这一切都取决于。
一些更合理的例子:
class Point {
let x: Int
let y: Int
init(x: Int, y: Int) { self.x = x; self.y = y }
convenience init(x: Int) { self.init(x: x, y: 0) }
convenience init(y: Int) { self.init(x: 0, y: y) }
convenience init(polar: (radius: Double, angle: Double)) { self.init(x: Int(cos(polar.angle)*polar.radius), y: Int(sin(polar.angle)*polar.radius)) }
}
class NumericValueAsString {
let stringValue: String // A value represented as "123.456"
init(stringValue: String) { self.stringValue = stringValue }
convenience init(value: Int) { self.init(stringValue: .init(value)) }
convenience init(integerPart: String, fractionPart: String) { self.init(stringValue: integerPart + "." + fractionPart) }
}
还有; required 关键字与此上下文中的任何内容无关。您可以将它放置到任何初始化器(指定或方便)、多个甚至所有初始化器中。
根据评论添加额外信息:
你的例子表明你可以有一个方便的 init 可以通过
参数返回到所需的 init``。我的情况怎么样
没有方便的 init``` 可以将值传递给参数
一个在必需的 init 中,但不在便利的 init 中。喜欢我的
我原来的问题中的速度参数。
这实际上取决于您的示例中未完全显示的类的接口。比如speed是否公开?
如果速度是公开的,那么您正在寻找的是类似的东西
let itemInstance = MyItem()
itemInstance.timeStamp = timeStamp
itemInstance.position = position
itemInstance.distance = distance
itemInstance.speed = speed
或
let itemInstance = MyItem(timeStamp: timeStamp, position: position, distance: distance)
itemInstance.speed = speed
甚至创建一个新的便利构造函数
extension MyItem {
convenience init(timeStamp: FitTime? = nil,
position: Position? = nil,
distance: Measurement<UnitLength>? = nil
speed: Speed? = nil
) {
self.init(timeStamp: timeStamp, position: position, distance: distance)
self.speed = speed
}
}
let itemInstance = MyItem(timeStamp: timeStamp, position: position, distance: distance, speed: speed)
但是,如果您的 speed 属性是私有定义的,那么您只能在内部分配给它。您需要能够修改您的类,以便它可以在某处接受此属性。通过构造函数、属性或方法。在完全没有访问权限之前,您不能指望能够修改它。
但如果这是你自己的班级,我会尽可能把事情颠倒过来。您的主要构造函数应该是接受所有 4 个参数的构造函数。但是应该需要您的便利初始化程序(是的,可能需要便利初始化程序)。因此,在这种情况下,您将拥有:
public required convenience init() {
self.init(timeStamp: self, position: self, distance: self, speed: self)
}
public init(timeStamp: FitTime? = nil,
position: Position? = nil,
distance: Measurement<UnitLength>? = nil,
speed: Speed?) {
super.init()
self.timeStamp = timeStamp
self.position = position
self.distance = distance
self.speed = speed
}
}
与您的代码相比,此特定案例感觉像是缺少某些内容,但同样,您没有提供类的完整定义,并且它确实或应该这样做。例如,在您提供的代码中,如果有人会调用便利初始化程序,那么以下行将按此顺序执行:
self.$timeStamp.owner = self // from self.init()
self.timeStamp = timeStamp
这似乎是个问题。
所以总结一下。有很多方法可以实现您的要求。但这一切都取决于您要在这里构建什么。
我希望它至少能让你走上正轨。