你能有条件地扩展 RawRepresentable 以符合另一个协议吗?

Can you conditionally extend RawRepresentable to conform to another protocol?

有没有办法让已经符合 RawRepresentable 的类型符合协议?

考虑一个 class 的基本示例,它可以在 sqlite 数据库中存储原始值:

protocol DatabaseStoreable {}

extension Int: DatabaseStoreable {}
extension Double: DatabaseStoreable {}
extension String: DatabaseStoreable {}
extension Data: DatabaseStoreable {}

func storeValue<T: DatabaseStoreable>(_ value: T) {
  ...
}

我还想包含任何符合 RawRepresentable 的类型,其中 RawValue: DatabaseStorable:

extension RawRepresentable: DatabaseStoreable where Self.RawValue: DatabaseStoreable {}

但是,这会产生以下错误:

Extension of protocol 'RawRepresentable' cannot have an inheritance clause

有没有办法解决这个问题,因为目前我必须声明具有以下签名的第二个函数:

func storeValue<T: RawRepresentable>(_ value: T) where T.RawValue: DatabaseStoreable {
  // Calls through to the function above.
}

您可以利用条件一致性做这样的事情:

extension RawRepresentable where RawValue: DatabaseStoreable {

    func storeValue<T: DatabaseStoreable>(_ value: T) {
        // do stuff
    }
}

enum Foo: String, DatabaseStoreable { 
    case bar
}

Foo.bar.storeValue("test")

顺便说一下:它应该是 DatabaseStorable 而不是 DatabaseStoreable

由于您的错误消息已经告诉您,无法向协议添加继承。您只能为对象添加继承。

因此这行不通:

extension RawRepresentable: DatabaseStoreable {}

但是,您可以像这样添加扩展名:

protocol DatabaseStoreable {}

extension Int: DatabaseStoreable {}
extension Double: DatabaseStoreable {}
extension String: DatabaseStoreable {}
extension Data: DatabaseStoreable {}

func storeValue<T: DatabaseStoreable>(_ value: T) {
     print("T store(\(value))")
}

extension RawRepresentable {
    func storeValue<T: DatabaseStoreable>(_ value: T) {
        print("RawRepresentable store(\(value))")
    }
}

enum Test: String {
    case A
    case B
}

class DataBaseStore: DatabaseStoreable {}

let myTest = Test.A
let databaseStore = DataBaseStore()
myTest.storeValue(databaseStore) // prints RawRepresentable store(__lldb_expr_15.DataBaseStore)