简体   繁体   中英

Method to return specialised type of generic protocol swift

I have a generic protocol which has a method that returns the generic parameter. There are two implementations of the protocol that both have string as the return type. I want a method to build a particular instance similar to a class cluster based on some parameter. The method constrains the generic type but there is an error when trying to return:

"Cannot convert return expression of type StringReturn into return type T"

protocol GenericProtocol {

    typealias ReturnType

    func doSomething() -> ReturnType

}

struct StringReturn : GenericProtocol {

    func doSomething() -> String {
        return "first"
    }

}

struct AnotherStringReturn : GenericProtocol {

    func doSomething() -> String {
        return "another"
    }

}

func build<T : GenericProtocol where T.ReturnType == String>(param: String) -> T {

    if .. {
        return StringReturn()
    } else {
        return AnotherStringReturn
    }

}

What you are trying to achieve is to use a generic function to create a instance of an object using Swift's Type Constraints.

Note the general syntax from Apple's documentation:

 func someFunction<T: SomeClass, U: SomeProtocol>(someT: T, someU: U) { // function body goes here }

In you function, it's not possible to infer at the time of function execution what type T is because you aren't passing it to the function as a parameter, hence you can't say what type is the output.

If you want to use a generic function with type constraints you could add some init to your protocol and use a function like this:

func build<T : GenericProtocol where T.ReturnType == String>(object: T.Type, param: String) -> T {
  // Your code here
  return T.init()
}

let str = build(StringReturn.self, param: "name")

Hope it helps!

It is possible to achieve using Opaque Types rather than Protocol generics at newest Swift versions.

Swift 5.3

You can think of an opaque type like being the reverse of a generic type. Generic types let the code that calls a function pick the type for that function's parameters and return value in a way that's abstracted away from the function implementation. For example, the function in the following code returns a type that depends on its caller:

Apple documentation

Example

protocol Fighter { }
struct XWing: Fighter { }

func launchFighter() -> Fighter {
    XWing()
}

let red5 = launchFighter()

It needs keyword some before your protocol name:

func launchOpaqueFighter() -> some Fighter {
    XWing()
}

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