简体   繁体   中英

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?

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

}

"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, eg

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

You can access this type eg 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, eg:

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)

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'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM