damian
damian

Reputation: 53

How to use associated type protocol as argument's type to a function?

Here's the simplified code that I have:

class MyClass {
    func returnSomething(argument: Protocol2) {}
}

protocol Protocol2: Protocol1 where E == Int {
}

protocol Protocol1 {
    associatedtype E
    func doSomething(_ value: E)
}

Compiler gives me the following error: Protocol 'Protocol2' can only be used as a generic constraint because it has Self or associated type requirements.

I understand that associated type E needs to be resolved before the protocol can be used as an argument in a function, but given that Protocol2 provides that information, why I still cannot compile that code?

Upvotes: 3

Views: 1387

Answers (3)

damian
damian

Reputation: 53

Swift compiler converted my typealias to the where clause. (Typealias overriding associated type 'E' from protocol 'Protocol1' is better expressed as same-type constraint on the protocol)

Passing argument indeed works with aforementioned syntax, thank you all!

But how would you return an instance that conforms to Protocol2?

class ClassConformsToProto2: Protocol2 {
    func doSomething(_ value: Int) {
}
}

class MyClass {
    func returnSomething<T: Protocol2>() -> T {
        return ClassConformsToProto2()
    }
}

This code doesn't work.

Cannot convert return expression of type 'ClasConformsToProto2' to return type 'T'

Upvotes: 0

dfrib
dfrib

Reputation: 73176

"How to use associated type protocol as argument's type to a function?"

I might not be following what you're asking here, but if a protocol of yours have an associated type, e.g.

protocol DummyNumericTypeWrapper {
    associatedtype U: Numeric
    static func magic(_ bar: U) -> U
}

You can access this type e.g. in a generic context where the generic placeholder has been constrained to your protocol. To follow up the dummy wrapper above with an entirely dummy example, e.g.:

extension StupidNumericTypeWrapper where U == Int {
    static func magic(_ bar: Int) -> Int {
        return bar + 42
    }
}

func foo<T: StupidNumericTypeWrapper>(_ bar: T.U, _ _ : T.Type) -> T.U {
    return T.magic(bar) * T.magic(bar)
}

struct DefaultMagic: StupidNumericTypeWrapper { }

let num = foo(1, DefaultMagic.self)
print(num) // 1849  (43*43)

Upvotes: 0

3stud1ant3
3stud1ant3

Reputation: 3606

Since I am learning about Swift generics , so I want to give it a go:

If you want to use Protocol2 as the type of argument in the function returnSomething

As suggested by @Nicolas Miari

class MyClass {
    func returnSomething<T: Protocol2>(argument: T) {}
}

Now as the name suggests this function should return something

so

class MyClass {
    func returnSomething<T: Protocol2>(argument: T) -> T {
            return argument
    }
}

Another issue that I see in the original problem is the use of where clause

I think you want to say the associated type of Protocol1 is Int

you should do it like this

protocol Protocol2: Protocol1 {
      typealias E = Int

}

Upvotes: 3

Related Questions