10

Is there a way that I could get the Class type or Struct type that extended my Protocol?

Here are my sample code:

protocol a {}

extension a {
    static func list(completion: ([StructType] -> Void)) {
        var items = [StructType]()
        ...
        completion(items)
    }
}

struct b{}
extension b: a {}

struct c{}
extension c: a{}

In this case I want to dynamically get the type of struct a and b, so that I could generate a list of it and return.

Thank you in advance for kindly answering my question.

Norak
  • 448
  • 1
  • 9
  • 22

1 Answers1

6

Use the Self keyword

protocol P {
    init()
}

extension P {
    static func list(completion: ([Self]) -> Void) {
        let items = [Self(), Self(), Self()]
        print(Self.self)
        completion(items)
    }
}

struct B {}
extension B: P {}

class C {
    required init() {}
}
extension C: P {}

B.list{ print($0) }
C.list{ print($0) }
Alexander
  • 59,041
  • 12
  • 98
  • 151
  • Thank you so much for quick reply. – Norak Mar 06 '17 at 09:29
  • You sir save me. – Norak Mar 06 '17 at 09:36
  • `type(of: self)` might be better. It gets the dynamic type of the object, so if you have class `D` that inherits from `C` it will give you the answer `D` (`Self` will still be `C`). – JeremyP Mar 06 '17 at 09:36
  • @JeremyP You mean `self` (given that it's at static level) – that would give you the dynamic value of the metatype that the method is called on. Although I agree it's worth noting the difference between `self` and `Self` in this context, as the results can be quite surprising in some cases as [this Q&A](http://stackoverflow.com/q/42037852/2976878) shows. – Hamish Mar 06 '17 at 10:21
  • @Hamish `Self` is the static type. `Self.self` gives you the meta object for the static type. So it will always give you a `C`. That might be what you want, particularly if you are using it to instantiate objects. – JeremyP Mar 06 '17 at 10:32
  • @JeremyP Yes, I know. I don't believe I said otherwise? Although it's not quite "always give you a `C`" – for `D.list{...}`, `Self` will be `D`. It's just the case of `let c : C.Type = D.self; c.list{...}` where `self` vs. `Self` makes the difference for static methods. – Hamish Mar 06 '17 at 10:56
  • @Hamish I take back what I said, you are correct in this case. – JeremyP Mar 06 '17 at 11:04
  • I'm not really sure but in this case static is better for because I need to instantiate that *B* and *C* – Norak Mar 07 '17 at 04:59
  • 1
    @Norak I was just keeping it as close to your example as possible – Alexander Mar 07 '17 at 05:07