gpt4 book ai didi

swift - 使用带有类型别名的协议(protocol)作为属性

转载 作者:搜寻专家 更新时间:2023-10-30 23:15:20 24 4
gpt4 key购买 nike

我有一个带有类型别名的协议(protocol):

protocol Archivable {
typealias DataType

func save(data: DataType, withNewName newName: String) throws
func load(fromFileName fileName: String) throws -> DataType
}

和一个符合该协议(protocol)的类:

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发表在评论中,你可以实现你想要做的事情。由于您的属性(property)在 TestClass似乎是一个 let,我假设你已经知道 DataType 的类型在编译时。首先你需要设置一个类型 erased 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 as an AnyArchiver<Int> .这样做将确保您不必创建十几个协议(protocol)来定义什么 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以防您在使用此方法时遇到任何问题。希望对您有所帮助!

关于swift - 使用带有类型别名的协议(protocol)作为属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34119887/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com