Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to require a generic type implement a generic protocol using a specific type in the protocol

Hi I'm using generics a lot in my current project. However, I've come across a problem:

I need a generic function foo<T> to be able to take a parameter that conforms to a generic protocol using a specific type.

For example in Java I can do:

public interface Proto<B> {
    public void SomeFunction()
}
public class SampleClass {
}
public class Conforms extends Proto<SampleClass> {
    @Override
    public void SomeFunction () {}
}
public class TestingClass {
    public void Requires (Proto<SampleClass> param) {
        // I can use param
    }
}

How would I do the same Requires() function in Swift? I know in Swift you use typealias in the protocol for generics. How do I constrain a parameter based on the typealias?

like image 491
Zenton Avatar asked Jul 03 '14 18:07

Zenton


2 Answers

Prototypes don't seem to have generics the way classes and structs do in Swift, but you can have associated types with typealias, which are close.

You can use type constraints to make sure that the object you pass in adopts the Proto with type constraints. To make the Proto you pass into require has the right B, you use where.

Apples documentation on generics has a lot of info.

This blog post is also a good source of info on doing more complicated things with generics.

protocol Proto {
    typealias B
    func someFunction()
}

class SampleClass {}

class Conforms : Proto {
    typealias B = SampleClass
    func someFunction() { }
}

class TestingClass {
    func requires<T: Proto where T.B == SampleClass>(param: T) {
        param.someFunction()
    }
}
like image 98
katfang Avatar answered Nov 15 '22 20:11

katfang


You can use a where clause to specify multiple requirements for a generic. I think your example translates to this, but it crashes Xcode. Beta!

protocol Proto {
    func someFunction()
}
class SampleClass {
}
class Conforms: SampleClass, Proto {
    func someFunction() {
    }
}
class TestingClass {
    func requires<T: SampleClass >(param: T) where T: Proto {
        param.someFunction()    // it's this line that kills Xcode
    }
}

let testingClass = TestingClass()
let conforms = Conforms()
testingClass.requires(conforms)
like image 26
Nate Cook Avatar answered Nov 15 '22 21:11

Nate Cook