首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用扩展实现Swift中的协议

使用扩展实现Swift中的协议
EN

Stack Overflow用户
提问于 2018-01-04 01:09:30
回答 2查看 69关注 0票数 2

我有一个Swift协议定义如下:

代码语言:javascript
复制
protocol SmartContract {

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

我在SmartContract上有一个扩展,定义如下:

代码语言:javascript
复制
extension SmartContract {

    mutating func addBrokenRule(_ brokenRule :BrokenRule) {

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

        self.brokenRules.append(brokenRule)
    }
}

我还有一个类MoneyTransferContract,它符合协议,但不定义brokenRules。这是因为我在扩展中定义了brokenRules

代码语言:javascript
复制
class MoneyTransferContract : SmartContract { 

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

我的问题是如何确保MoneyTransformContract符合SmartContract协议。是否有BrokenRule可供MoneyTransformContract使用,而无需在不同的SmartContracts中一次又一次地定义它。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-01-04 02:26:30

约翰·多伊写道:

是否有BrokenRule可供MoneyTransformContract使用,而无需在不同的SmartContracts中一次又一次地定义它。

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

代码语言:javascript
复制
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.
}
票数 2
EN

Stack Overflow用户

发布于 2018-01-04 02:07:21

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

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

代码语言:javascript
复制
extension SmartContract {
    var brokenRules: [BrokenRule] {
        get { return [] }
        set(newRules) { }
    }
}

但这意味着,任何忘记为brokenRules指定自己的实现的实现类型都有一个brokenRules属性,该属性总是解析为空数组。

原因之一是Swift的计算属性。对于某些实现类型,将brokenRules存储为数组可能没有意义--而协议不能强制这样做。这是协议作者不能(也不应该)担心的实现细节。例如,如果BrokenRules可以很容易地转换到字符串和字符串之间,那么您可以想象有一个类实现了SmartContract,如下所示:

代码语言:javascript
复制
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(_:)指定一个实现。这就是你的协议扩展让你。通过在扩展中提供实现,可以确保所有实现类型都具有函数的默认实现,因此它们可以选择放弃定义自己的实现。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48087363

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档