Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a protocol with a generic function extending type

I'm trying to do a protocol with a generic function where T is not just equal to the type, but extends it.

class MainItem {}
class Item1: MainItem {}
class Item2: MainItem {}

protocol MyProtocol {
    func myFunc<T: MainItem>() -> T // T extends MainItem
}

class ClassA: MyProtocol {
    func myFunc() -> Item1 { // not MainItem
        return Item1()
    }
}

class ClassB: MyProtocol {
    func myFunc() -> Item2 { // not MainItem
        return Item2()
    }
}

But I get this error

Type 'ClassA' does not conform to protocol 'MyProtocol'

because Item1 is not equal to MainItem (it expands it). How can you make it work?

For example, in Java everything can be done using abstract class:

abstract class MyProtocol {
    abstract <T extends MainItem> T myFunc()
}
like image 478
Vergiliy Avatar asked Jul 20 '26 19:07

Vergiliy


1 Answers

Generics is not the way to go for your requirements. When you declare a generic function in a protocol, the generic type parameter will mean that the same function works for all types that satisfy the generic type restriction, but the function signature still needs to be intact for all conforming types.

What you are looking for is a protocol with associated type. An associated type on a protocol means that the conforming type can decide what concrete type to use in place of the associated type, hence allowing you to use different associated types in different conforming classes.

protocol MyProtocol {
    associatedtype MyType: MainItem
    func myFunc() -> MyType
}

class ClassA: MyProtocol {
    func myFunc() -> Item1 {
        return Item1()
    }
}

class ClassB: MyProtocol {
    func myFunc() -> Item2 {
        return Item2()
    }
}
like image 165
Dávid Pásztor Avatar answered Jul 23 '26 08:07

Dávid Pásztor



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!