使用扩展符合Swift中的协议

使用扩展符合Swift中的协议,swift,Swift,我的Swift协议定义如下: protocol SmartContract { func apply(transaction :Transaction) func addBrokenRule(_ brokenRule: BrokenRule) var brokenRules :[BrokenRule] { get set } } extension SmartContract { mutating func addBrokenRule(_ brokenRu

我的Swift协议定义如下:

protocol SmartContract {

    func apply(transaction :Transaction)
    func addBrokenRule(_ brokenRule: BrokenRule)
    var brokenRules :[BrokenRule] { get set }
} 
extension SmartContract {

    mutating func addBrokenRule(_ brokenRule :BrokenRule) {

        if self.brokenRules == nil {
            self.brokenRules = [BrokenRule]()
        }

        self.brokenRules.append(brokenRule)
    }
}
我对SmartContract进行了如下扩展:

protocol SmartContract {

    func apply(transaction :Transaction)
    func addBrokenRule(_ brokenRule: BrokenRule)
    var brokenRules :[BrokenRule] { get set }
} 
extension SmartContract {

    mutating func addBrokenRule(_ brokenRule :BrokenRule) {

        if self.brokenRules == nil {
            self.brokenRules = [BrokenRule]()
        }

        self.brokenRules.append(brokenRule)
    }
}
我还有一个MoneyTransferContract类,它符合协议,但没有定义
代理规则。这是因为我在扩展中定义了
brokenRules

class MoneyTransferContract : SmartContract { 

     func apply(transaction :Transaction) { // do something here }
}

我的问题是如何确保MoneyTransformContract符合SmartContract协议。MoneyTransformContract是否可以使用BrokerRule,而无需在不同的SmartContract中反复定义它

如果我理解正确,就没有办法做你想做的事。(编辑:正如Jeff所指出的,如果您想使用继承而不是协议,这是可能的。如何使用,请参见他的答案)。Swift中的协议只是由实现类型来正确定义的需求列表。协议通常对实现类型的实际行为或实现没有任何发言权,只保证属性和函数存在。您的
SmartContract
协议规定,每个
SmartContract
必须具有一个函数
apply(事务:)
、一个函数
addbrokerrule(:)
,以及一个可访问和修改的属性
brokerrules

当一个类型实现
SmartContract
时,它必须定义其中的每一个。正如您必须写出签名来告诉编译器您正在实现
apply(transaction:)
,您还必须告诉编译器如何实现属性
brokenRules
。通过将具有
brokenRules
的扩展定义为计算属性(本质上是no-op),您可以以某种无用的方式获得此功能:

extension SmartContract {
    var brokenRules: [BrokenRule] {
        get { return [] }
        set(newRules) { }
    }
}
但这意味着任何忘记为
brokenRules
指定自己的实现的实现类型都将具有
brokenRules
属性,该属性始终解析为空数组

原因之一是斯威夫特的计算属性。对于某些实现类型,将
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 = ""
    }
}
请注意,我们不必为
AddBrokerRule(:)
指定实现。这就是你的协议扩展给你的。通过在扩展中提供实现,您可以确保所有实现类型都有函数的默认实现,因此它们可以选择放弃定义自己的实现。

john doe写道:

MoneyTransformContract是否可以使用BrokerRule,而无需在不同的SmartContract中反复定义它

您需要的是该行为的超类/子类关系

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.
}

你知道编写更地道的Swift的指南的链接吗?苹果的书《Swift编程》在这方面做得很好。你可以查看这些代码片段,了解哪些模式被认为是“正确”的做事方式。我不知道还有什么更明确的指南。我的感觉主要是从阅读这本书和看到邮件列表上的代码片段发展而来的。