swift – 使用带有typealias的协议作为属性

swift – 使用带有typealias的协议作为属性,第1张

概述我有一个带有typealias的协议: protocol Archivable { typealias DataType func save(data: DataType, withNewName newName: String) throws func load(fromFileName fileName: String) throws -> DataType} 以及 我有一个带有typealias的协议:

protocol Archivable {    typealias DataType    func save(data: DataType,withNewname newname: String) throws    func load(fromfilename filename: String) throws -> DataType}

以及符合该协议的类:

class Archiver: Archivable {    typealias DataType = Int    func save(data: DataType,withNewname newname: String) throws {        //saving    }    func load(fromfilename filename: String) throws -> DataType {        //loading    }}

我想在另一个类中使用Archivable作为属性,如:

class TestClass {    let arciver: Archivable = Archiver() //error here: Protocol 'Archivable' can only be used as a generic constraint because it has Self or associated type requiments}

但它失败了

Protocol ‘Archivable’ can only be used as a generic constraint because it has Self or associated type requiments

我的目标是TestClass只能看到Archiver为Archiveable,所以如果我想更改保存/加载机制,我只需要创建一个符合Archivable的新类,因为它设置为TestClass中的属性,但我不是知道这是否有道理,如果是,那么如何.

我想避免使用AnyObject而不是DataType.

解决方法 根据您实际尝试的 *** 作,这可以使用类型擦除.如果您按照评论中发布的链接 R Menke中的说明 *** 作,则可以实现您的目标.由于TestClass中的属性似乎是一个let,我假设你已经知道编译时DataType的类型.首先,您需要设置类型已删除的Archivable类,如下所示:

class AnyArchiver<T>: Archivable {    private let _save: ((T,String) throws -> VoID)    private let _load: (String throws -> T)    init<U: Archivable where U.DataType == T>(_ archiver: U) {        _save = archiver.save        _load = archiver.load    }    func save(data: T,withNewname newname: String) throws {        try _save(data,newname)    }    func load(fromfilename filename: String) throws -> T {        return try _load(filename)    }}

就像Swift的AnySequence一样,你可以将你的Archiver包装在TestClass中的这个类中,如下所示:

class TestClass {    let archiver = AnyArchiver(Archiver())}

通过类型推断,Swift将输入TestClass的archiver let constant作为AnyArchiver< Int>.这样做将确保您不必创建十几个协议来定义DataType,如StringArchiver,ArrayArchiver,IntArchiver等.您可以选择使用泛型来定义变量,如下所示:

let intArchiver: AnyArchiver<Int>let stringArchiver: AnyArchiver<String>let modelArchiver: AnyArchiver<Model>

而不是复制像这样的代码:

protocol IntArchivable: Archivable {    func save(data: Int,withNewname newname: String) throws    func load(fromfilename filename: String) throws -> Int}protocol StringArchivable: Archivable {    func save(data: String,withNewname newname: String) throws    func load(fromfilename filename: String) throws -> String}protocol ModelArchivable: Archivable {    func save(data: Model,withNewname newname: String) throws    func load(fromfilename filename: String) throws -> Model}let intArchiver: IntArchivablelet stringArchiver: StringArchivablelet modelArchiver: ModelArchivable

我写了一篇关于goes into even more detail的帖子,以防你遇到这种方法的任何问题.我希望这有帮助!

总结

以上是内存溢出为你收集整理的swift – 使用带有typealias的协议作为属性全部内容,希望文章能够帮你解决swift – 使用带有typealias的协议作为属性所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1003893.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-22
下一篇 2022-05-22

发表评论

登录后才能评论

评论列表(0条)

保存