Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
141 views
in Technique[技术] by (71.8m points)

How do I specify that a non-generic Swift type should comply to a protocol?

I'd like to implement a Swift method that takes in a certain class type, but only takes instances of those classes that comply to a specific protocol. For example, in Objective-C I have this method:

- (void)addFilter:(GPUImageOutput<GPUImageInput> *)newFilter;

where GPUImageOutput is a particular class, and GPUImageInput is a protocol. Only GPUImageOutput classes that comply to this protocol are acceptable inputs for this method.

However, the automatic Swift-generated version of the above is

func addFilter(newFilter: GPUImageOutput!)

This removes the requirement that GPUImageOutput classes comply with the GPUImageInput protocol, which will allow non-compliant objects to be passed in (and then crash at runtime). When I attempt to define this as GPUImageOutput<GPUImageInput>, the compiler throws an error of

Cannot specialize non-generic type 'GPUImageOutput'

How would I do such a class and protocol specialization in a parameter in Swift?

question from:https://stackoverflow.com/questions/24455327/how-do-i-specify-that-a-non-generic-swift-type-should-comply-to-a-protocol

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Is swift you must use generics, in this way:

Given these example declarations of protocol, main class and subclass:

protocol ExampleProtocol {
    func printTest()   // classes that implements this protocol must have this method
}

// an empty test class
class ATestClass
{

}

// a child class that implements the protocol
class ATestClassChild : ATestClass, ExampleProtocol
{
    func printTest()
    {
        println("hello")
    }
}

Now, you want to define a method that takes an input parameters of type ATestClass (or a child) that conforms to the protocol ExampleProtocol. Write the method declaration like this:

func addFilter<T where T: ATestClass, T: ExampleProtocol>(newFilter: T)
{
    println(newFilter)
}

Your method, redefined in swift, should be

func addFilter<T where T:GPUImageOutput, T:GPUImageInput>(newFilter:T!)
{
    // ...
}

EDIT:

as your last comment, an example with generics on an Enum

    enum OptionalValue<T> {
        case None
        case Some(T)
    }
    var possibleInteger: OptionalValue<Int> = .None
    possibleInteger = .Some(100)

Specialized with protocol conformance:

    enum OptionalValue<T where T:GPUImageOutput, T:GPUImageInput> {
        case None
        case Some(T)
    }

EDIT^2:

you can use generics even with instance variables:

Let's say you have a class and an instance variable, you want that this instance variable takes only values of the type ATestClass and that conforms to ExampleProtocol

class GiveMeAGeneric<T: ATestClass where T: ExampleProtocol>
{
    var aGenericVar : T?
}

Then instantiate it in this way:

    var child = ATestClassChild()
    let aGen = GiveMeAGeneric<ATestClassChild>()
    aGen.aGenericVar = child

If child doesn't conform to the protocol ExampleProtocol, it won't compile


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...