我有一个Swift协议定义如下:
protocol SmartContract {
func apply(transaction :Transaction)
func addBrokenRule(_ brokenRule: BrokenRule)
var brokenRules :[BrokenRule] { get set }
} 我在SmartContract上有一个扩展,定义如下:
extension SmartContract {
mutating func addBrokenRule(_ brokenRule :BrokenRule) {
if self.brokenRules == nil {
self.brokenRules = [BrokenRule]()
}
self.brokenRules.append(brokenRule)
}
}我还有一个类MoneyTransferContract,它符合协议,但不定义brokenRules。这是因为我在扩展中定义了brokenRules。
class MoneyTransferContract : SmartContract {
func apply(transaction :Transaction) { // do something here }
}我的问题是如何确保MoneyTransformContract符合SmartContract协议。是否有BrokenRule可供MoneyTransformContract使用,而无需在不同的SmartContracts中一次又一次地定义它。
发布于 2018-01-04 02:26:30
约翰·多伊写道:
是否有BrokenRule可供MoneyTransformContract使用,而无需在不同的SmartContracts中一次又一次地定义它。
您需要的是该行为的超类/子类关系。
class SmartContract {
func apply(transaction :Transaction) {
//implemention
}
var brokenRules: [BrokenRule] = []
func addBrokenRule(_ brokenRule :BrokenRule) {
brokenRules.append(brokenRule)
}
}
class MoneyTransferContract : SmartContract {
// Gets `brokenRules` for free from superclass.
}
class BitCoinTransferContract : SmartContract {
// Gets `brokenRules` for free from superclass.
}发布于 2018-01-04 02:07:21
如果我理解正确,就没有办法做你想做的事。(编辑:正如Jeff指出的,如果您想使用继承而不是协议,这是可能的。见他如何回答)。Swift中的协议只是需要实现类型才能正确定义的需求列表。协议通常对实现类型的实际行为或实现没有任何发言权,只保证存在属性和函数。您的SmartContract协议规定,每个SmartContract都必须有一个函数apply(transaction:)、一个函数addBrokenRule(_:)和一个可以访问和修改的属性brokenRules。
当一个类型实现SmartContract时,它必须定义其中的每一个。正如您必须写出签名才能告诉编译器您正在实现apply(transaction:)一样,您还必须告诉编译器如何实现属性brokenRules。您可以以一种有些无用的方式获得此功能,方法是将具有brokenRules的扩展定义为计算属性,该属性本质上是无操作的:
extension SmartContract {
var brokenRules: [BrokenRule] {
get { return [] }
set(newRules) { }
}
}但这意味着,任何忘记为brokenRules指定自己的实现的实现类型都有一个brokenRules属性,该属性总是解析为空数组。
原因之一是Swift的计算属性。对于某些实现类型,将brokenRules存储为数组可能没有意义--而协议不能强制这样做。这是协议作者不能(也不应该)担心的实现细节。例如,如果BrokenRules可以很容易地转换到字符串和字符串之间,那么您可以想象有一个类实现了SmartContract,如下所示:
class StringContract: SmartContract {
var ruleString: String
var brokenRules: [BrokenRule] {
get {
let stringArray = ruleString.split(separator: ",")
return stringArray.map { BrokenRule(string:String($0)) }
}
set(newRules) {
let stringArray = newRules.map { $0.stringValue }
ruleString = stringArray.joined(separator: ",")
}
}
func apply(transaction: Transaction) {
// do something here...
}
init() {
ruleString = ""
}
}注意,我们不需要为addBrokenRule(_:)指定一个实现。这就是你的协议扩展让你。通过在扩展中提供实现,可以确保所有实现类型都具有函数的默认实现,因此它们可以选择放弃定义自己的实现。
https://stackoverflow.com/questions/48087363
复制相似问题