0

I want to implement a printable function for my protocol in the protocol extension, then any struct which conformed the protocol will be printed based on the fields of protocol. But I got the following error, it seems swift does not allow this. Should I extend String and add a init(_:Info) {...} for it?

protocol Info {
    var name: String { get }
    var serial: Int { get }
}
struct Person : Info {
    var name = ""
    var serial = 0
}

extension Info : CustomStringConvertible {
                 ^~~~~~~~~~~~~~~~~~~~~~~
                 error: extension of protocol 'Info' cannot have an inheritance clause

    var description: String {
        return "\(name) + \(serial)"
    }
}
func print(info: Info) {
    print(info)
}
Chen OT
  • 3,486
  • 2
  • 24
  • 46
  • 3
    Related (if not duplicate): [Swift: Is it possible to add a protocol extension to a protocol?](https://stackoverflow.com/questions/41993616/swift-is-it-possible-to-add-a-protocol-extension-to-a-protocol) – Martin R Oct 03 '19 at 09:09
  • 1
    Also: [Swift 2 add protocol conformance to protocols](https://stackoverflow.com/questions/31491638/swift-2-add-protocol-conformance-to-protocols). – Martin R Oct 03 '19 at 09:12

2 Answers2

3

You should inherit the protocol in the definition, not in the extension.

protocol Info: CustomStringConvertible {
    var name: String { get }
    var serial: Int { get }
}
struct Person : Info {
    var name = ""
    var serial = 0
}

extension Info  {
    var description: String {
        return "\(name) + \(serial)"
    }
}
func print(info: Info) {
    print(info)
}
Vyacheslav
  • 26,359
  • 19
  • 112
  • 194
3

You need to make your protocol conform to CustomStringConvertible. Then in your extension of Info you can give your default method. As below.

protocol Info: CustomStringConvertible {
    var name: String { get }
    var serial: Int { get }
}

struct Person: Info {
    var name = ""
    var serial = 0
}

extension Info {
    var description: String {
        return "\(name) + \(serial)"
    }
}

func print(info: Info) {
    print(info)
}

It is because a constraint is needed for conformance purposes, otherwise, the compiler thinks it is an inheritance

An alternative way is to do the following:

protocol Info {
    var name: String { get }
    var serial: Int { get }
}

struct Person: Info, CustomStringConvertible { // notice that Person now conforms to CustomStringConvertible
    var name = ""
    var serial = 0
}

// the extension only applies to objects that themselves conform to CustomStringConvertible
extension Info where Self: CustomStringConvertible  {
    var description: String {
        return "\(name) + \(serial)"
    }
}
Andrew
  • 26,706
  • 9
  • 85
  • 101