加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-14 04:33:43 所属栏目:百科 来源:网络整理
导读:我有一个带有typealias的协议: protocol Archivable { typealias DataType func save(data: DataType,withNewName newName: String) throws func load(fromFileName fileName: String) throws - DataType} 以及符合该协议的类: class Archiver: Archivable
我有一个带有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: IntArchivable
let stringArchiver: StringArchivable
let modelArchiver: ModelArchivable

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读