gpt4 book ai didi

swift - 如何创建符合具有嵌套 PAT 的协议(protocol)的类?

转载 作者:行者123 更新时间:2023-11-30 11:56:08 26 4
gpt4 key购买 nike

我正在尝试使用类型删除来创建 Repository可以遵循的协议(protocol)(类似于 Swift 的 AnyCollection )。该协议(protocol)需要包装在类型删除的类中,因为它包含 PAT。

但是,由于该协议(protocol)有一个嵌套协议(protocol),该协议(protocol)也有一个 PAT,所以它使事情变得有些复杂。

  • Keyable是提供 key 的东西(最终我想确保也是 Hashable ...一次一件事)。
  • Repository是我的广义“容器”协议(protocol)
  • AnyKeyable Keyable 的类型删除包装
  • AnyRepository Repository 的类型删除包装

我有一个几乎编译的 Playground 片段:

protocol Keyable {
associatedtype KeyType// where KeyType: Hashable
func key() -> KeyType
}

protocol Repository {
associatedtype DataType: Keyable
func all() -> [DataType]
func get(id: DataType.KeyType) throws -> DataType?
func create(object: DataType) throws -> Bool
func update(object: DataType) throws -> Bool
func delete(object: DataType) throws -> Bool
func clear() -> Bool
}

final class AnyKeyable<T>: Keyable {
private let _key: () -> T
init<U: Keyable>(_ keyable: U) where U.KeyType == T {
_key = keyable.key
}

public func key() -> T {
return _key()
}
}

final class AnyRepository<T: Keyable>: Repository {
private let _all: () -> [T]
private let _get: (_ id: T.KeyType) throws -> T?
private let _create: (_ object: T) throws -> Bool
private let _update: (_ object: T) throws -> Bool
private let _delete: (_ object: T) throws -> Bool
private let _clear: () -> Bool

init<U: Repository>(_ repository: U) where U.DataType == T {
_get = repository.get
_create = repository.create
_delete = repository.delete
_update = repository.update
_clear = repository.clear
_all = repository.all
}

func all() -> [T] {
return _all()
}

func get<K: Keyable>(id: K.KeyType) throws -> T? where T.KeyType: Keyable, T.KeyType == K.KeyType {
let anyKeyable = AnyKeyable(id)
return try _get(anyKeyable)
}

func create(object: T) throws -> Bool {
return try _create(object)
}

func update(object: T) throws -> Bool {
return try _update(object)
}

func delete(object: T) throws -> Bool {
return try _delete(object)
}

func clear() -> Bool {
return _clear()
}
}

final class Contact {
var name: String = ""
var email: String = ""
}

extension Contact: Keyable {
public typealias KeyType = String
public func key() -> String {
return "im the key"
}
}

// Just a dummy class to see
final class ContactRepository: Repository {
typealias DataType = Contact
private var someContacts: [Contact] = []

func all() -> [Contact] {
return someContacts
}

func clear() -> Bool {
someContacts.removeAll()
return someContacts.count == 0
}

func get(id: Contact.KeyType) throws -> Contact? {
return nil
}

func update(object: Contact) throws -> Bool {
return false
}

func create(object: Contact) throws -> Bool {
return false
}

func delete(object: Contact) throws -> Bool {
return false
}
}

// Testing
let i = AnyRepository<Contact>(ContactRepository())
i.all()
i.clear()

问题是 Swift 编译器提示我没有使用 Kget<K: Keyable>(id: K.KeyType) 的方法签名中......但在我看来,我确实是。

我的想法是编译器因为DataType.KeyType而提示声明get()在协议(protocol)中,而不是在 AnyRepository 中具体子类,但我不确定如何纠正这个问题以为编译器提供更多上下文。

有没有更好的方法来构建它以允许我完成这个模式?也允许第一个associatedtype怎么样?在Keyable成为associatedtype KeyType where KeyType: Hashable

非常感谢任何帮助,谢谢!

最佳答案

正如 Hamish 指出的那样,没有必要引入另一个泛型 K。这让事情变得复杂了。清理完所有内容后,现在无需 AnyKeyable 类的复杂化即可工作:

public protocol Keyable {
associatedtype KeyType where KeyType: Hashable
func key() -> KeyType
}

public protocol Repository {
associatedtype DataType: Keyable
func all() -> [DataType]
func get(id: DataType.KeyType) throws -> DataType?
func create(object: DataType) throws
func create(objects: [DataType]) throws
func update(object: DataType) throws
func delete(object: DataType) throws
func delete(objects: [DataType]) throws
func clear()
}

public class AnyRepository<T: Keyable>: Repository {
private let _all: () -> [T]
private let _get: (_ id: T.KeyType) throws -> T?
private let _create: (_ object: T) throws -> Void
private let _createAll: (_ objects: [T]) throws -> Void
private let _update: (_ object: T) throws -> Void
private let _delete: (_ object: T) throws -> Void
private let _deleteAll: (_ objects: [T]) throws -> Void
private let _clear: () -> Void

public init<R: Repository>(_ repository: R) where R.DataType == T {
_get = repository.get
_create = repository.create
_createAll = repository.create
_delete = repository.delete
_deleteAll = repository.delete
_update = repository.update
_clear = repository.clear
_all = repository.all
}

public func all() -> [T] {
return _all()
}

public func get(id: T.KeyType) throws -> T? {
return try _get(id)
}

public func create(object: T) throws {
return try _create(object)
}

public func create(objects: [T]) throws {
return try _createAll(objects)
}

public func update(object: T) throws {
return try _update(object)
}

public func delete(object: T) throws {
return try _delete(object)
}

public func delete(objects: [T]) throws {
return try _deleteAll(objects)
}

public func clear() {
return _clear()
}
}

关于swift - 如何创建符合具有嵌套 PAT 的协议(protocol)的类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47799938/

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