0

Is there a way to add conformance to a protocol for types that already conform to RawRepresentable?

Consider a basic example of a class that can store primitive values in a sqlite database:

protocol DatabaseStoreable {}

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

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

I'd like to also include any type that conforms to RawRepresentable where RawValue: DatabaseStorable:

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

However, this generates the following error:

Extension of protocol 'RawRepresentable' cannot have an inheritance clause

Is there a way to work around this because at the moment I have to declare a second function with the following signature:

func storeValue<T: RawRepresentable>(_ value: T) where T.RawValue: DatabaseStoreable {
  // Calls through to the function above.
}
kennyc
  • 5,490
  • 5
  • 34
  • 57
  • 1
    Did you check https://stackoverflow.com/q/41993616 or https://stackoverflow.com/q/50966560 ? – Martin R May 11 '20 at 07:13
  • I was still confused after doing some initial research and was somewhat curious if anything had changed in recent versions of Swift given some of the updates that have appeared for SwiftUI. Regardless, that first link has an answer which references `SE-0143`, which in turn has a good summary under `Alternatives Considered` that I had missed. – kennyc May 11 '20 at 20:42
  • I think what you are describing translates to `extension RawRepresntable where Self : DatabaseStoreable, Self.RawValue : DatabaseStoreable {}`, I don't know if it will work though. – kumowoon1025 Jun 27 '20 at 21:46

2 Answers2

1

You could leverage on the conditional conformance doing something like this:

extension RawRepresentable where RawValue: DatabaseStoreable {

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

enum Foo: String, DatabaseStoreable { 
    case bar
}

Foo.bar.storeValue("test")

By the way: it should be DatabaseStorable and not DatabaseStoreable.

Mario
  • 470
  • 4
  • 9
0

As your error message is already telling you there is no way to add inheritance to protocols. You only can add inheritance to objects.

Therefore this won't work:

extension RawRepresentable: DatabaseStoreable {}

However, you could add an extension as this:

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)
hhamm
  • 1,511
  • 15
  • 22