How do you use protocol types?


(Karl) #1

So I’m trying to work generically to construct things based on their conformance to a protocol with an initialiser. I’m sure this worked before; I’ve done it before. Maybe there have been some changes in the language or something, because I’ve tried everywhich-way and this just isn’t flying:

···

==================
protocol AProto {

  associatedtype ElementType
  func constructInstance(_: ElementType.Type) -> ElementType
}

protocol SimpleConstructableElement {
  init()
}

extension Int : SimpleConstructableElement {}

class Factory : AProto {

  typealias ElementType = SimpleConstructableElement

  func constructInstance(_ t: SimpleConstructableElement.Type) -> SimpleConstructableElement {
    return t.init()
  }
}

Factory().constructInstance(Int.self)

/tmp/MyPlayground.playground:15:7: Type 'Factory' does not conform to protocol 'AProto'
/tmp/MyPlayground.playground:6:7: Protocol requires function 'constructInstance' with type '(ElementType.Protocol) -> ElementType'
/tmp/MyPlayground.playground:19:7: Candidate has non-matching type '(SimpleConstructableElement.Type) -> SimpleConstructableElement’

=================================

The thing that gets me about this is that Xcode’s code-completion tells me that SimpleConstructableElement.Type is of type SimpleConstructableElement.Protocol, so it should be the same as ElementType.Protocol and should be accepted, right?

Karl


(Dan Loewenherz) #2

Unless you need to abstract what the Factory class does, I would eliminate
AProto.

class Factory {

    func constructInstance<T: SimpleConstructableElement>(_ t: T.Type) -> T
{

        return t.init()

    }

}

If you truly want to genericize Factory, you can do the following:

class Factory<T: SimpleConstructableElement>: AProto {

    typealias ElementType = T

    func constructInstance(_ t: T.Type) -> T {

        return t.init()

    }

}

However, ElementType can be inferred, so you can zap it, and then you get
this:

class Factory<T: SimpleConstructableElement>: AProto {

    func constructInstance(_ t: T.Type) -> T {

        return t.init()

    }

}

…which compiles and I think does what you want it to. :slight_smile:

Dan

···

On Wed, Jul 13, 2016 at 8:58 PM, Karl via swift-users <swift-users@swift.org > wrote:

So I’m trying to work generically to construct things based on their
conformance to a protocol with an initialiser. I’m sure this worked before;
I’ve done it before. Maybe there have been some changes in the language or
something, because I’ve tried everywhich-way and this just isn’t flying:

==================
protocol AProto {

        associatedtype ElementType
        func constructInstance(_: ElementType.Type) -> ElementType
}

protocol SimpleConstructableElement {
        init()
}

extension Int : SimpleConstructableElement {}

class Factory : AProto {

        typealias ElementType = SimpleConstructableElement

        func constructInstance(_ t: SimpleConstructableElement.Type) ->
SimpleConstructableElement {
                return t.init()
        }
}

Factory().constructInstance(Int.self)

/tmp/MyPlayground.playground:15:7: Type 'Factory' does not conform to
protocol 'AProto'
/tmp/MyPlayground.playground:6:7: Protocol requires function
'constructInstance' with type '(ElementType.Protocol) -> ElementType'
/tmp/MyPlayground.playground:19:7: Candidate has non-matching type
'(SimpleConstructableElement.Type) -> SimpleConstructableElement’

=================================

The thing that gets me about this is that Xcode’s code-completion tells me
that SimpleConstructableElement.Type is of type
SimpleConstructableElement.Protocol, so it should be the same as
ElementType.Protocol and should be accepted, right?

Karl
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users