首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Swift协议需要属性作为协议

Swift协议需要属性作为协议
EN

Stack Overflow用户
提问于 2016-06-24 15:27:47
回答 2查看 2.4K关注 0票数 7

我正在尝试定义一个协议"Repository“,它需要定义一些属性(它们实现了一个特定的协议"DataSource")

但由于我实际场景的复杂性,其中一个属性需要是"DataSource“的子协议。

我将问题简化为以下简单代码:

代码语言:javascript
复制
protocol DataSource { }

protocol ExtraDataSouce: DataSource {
    func method1() -> String
}

struct MyDataSource: ExtraDataSouce {
    func method1() -> String {
        return "whatever"
    }
}


protocol Repository {
    var firstDataSource: DataSource { get }
    var secondDataSource: DataSource { get }
}

struct MyRepository: Repository {
    var firstDataSource: DataSource
    var secondDataSource: MyDataSource
}

这会在编译时返回一个错误,因为"MyRepository“不符合"Repository”。但我认为它实际上是...你知道为什么它不接受定义为"MyDataSource“的"MyRepository”中的"secondDataSource“吗?

EN

回答 2

Stack Overflow用户

发布于 2016-06-24 19:13:21

在搜索之后,我找到了关于你的问题的信息(如果我在哪里弄错了或者如果我漏掉了什么,请纠正我):

即使您的代码在逻辑上应该可以工作,当您在MyRepository类中声明常规或只读协议变量的类型时,swift编译器也不会区分大小写。换句话说,如果您要用Repository编写代码,那么代码中的错误就会变得显而易见

代码语言:javascript
复制
var secondDataSource: DataSource { get set }

编译器不会将这种情况分开。我没有找到完全正确的方法来做你想要的事情。但有两种接近的方法:

1)显而易见,也可能是最正确的方式-在MyRepository中更改secondDataSource类型,如果愿意,还可以使用其他变量:

代码语言:javascript
复制
var _secondDataSource: MyDataSource
var secondDataSource: DataSource {
        get {return _secondDataSource}
        set {
            guard let newValue = newValue as? MyDataSource else {
                fatalError("MyRepository: attempt to set DataSource type, MyDataSource type expected")
            }
            _secondDataSource = newValue
        }
    }

2)协议方式关联类型。在这里,我将改进@RaduNunu的回答,因为他的代码中的associatedtype type = DataSource行只有占位符效果,并且他的解决方案允许您选择采用任何类型的secondDataSource,例如String

代码语言:javascript
复制
protocol Repository {
    associatedtype Type = DataSource
    var firstDataSource: DataSource { get }
    var secondDataSource: Type { get }
}

struct MyRepository: Repository {
    var firstDataSource: DataSource
    var secondDataSource: String // - this is ok!
}

这段代码可以编译并工作,但它看起来很糟糕。而不是键入占位符,您最好使用协议一致性:

代码语言:javascript
复制
protocol Repository {
    associatedtype Type: DataSource
    var firstDataSource: DataSource { get }
    var secondDataSource: Type { get }
}

struct MyRepository: Repository {
    var firstDataSource: DataSource
    //var secondDataSource: String - this line not allowed now
    var secondDataSource: MyDataSource
}

这段代码已经非常接近目标了。但是,从现在开始,您不能使用协议作为关联类型,因此声明

代码语言:javascript
复制
var secondDataSource: DataSource

MyRepository中将不起作用。这是使用关联类型的代价:您只能使用符合DataSource的类/枚举/结构类型。

票数 3
EN

Stack Overflow用户

发布于 2016-06-24 15:50:24

您存储库协议实现了2个DataSource类型的变量,当您尝试修改符合存储库协议的结构中的变量类型时,它不允许您这样做,因为需要的类型。您应该使用关联类型来进行此更改

代码语言:javascript
复制
protocol Repository {
    associatedtype type = DataSource
    var firstDataSource: DataSource { get }
    var secondDataSource: type { get }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38007881

复制
相关文章

相似问题

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