首页 文章

如何指定非泛型Swift类型应符合协议?

提问于
浏览
42

我想实现一个接受某种类类型的Swift方法,但只接受那些符合特定协议的类的实例 . 例如,在Objective-C中我有这样的方法:

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

其中 GPUImageOutput 是特定类, GPUImageInput 是协议 . 只有符合此协议的 GPUImageOutput 类才是此方法的可接受输入 .

但是,上面的自动Swift生成的版本是

func addFilter(newFilter: GPUImageOutput!)

这消除了 GPUImageOutput 类符合 GPUImageInput 协议的要求,这将允许传入不兼容的对象(然后在运行时崩溃) . 当我尝试将其定义为 GPUImageOutput<GPUImageInput> 时,编译器会抛出错误

不能专门化非泛型类型'GPUImageOutput'

我如何在Swift中的参数中进行这样的类和协议专门化?

2 回答

  • 13

    你必须迅速使用泛型,这样:

    给出这些协议,主类和子类的示例声明:

    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")
        }
    }
    

    现在,您要定义一个方法,该方法接受符合协议ExampleProtocol的ATestClass类型(或子类)的输入参数 . 像这样编写方法声明:

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

    你的方法,在swift中重新定义,应该是

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

    编辑:

    作为你的最后一条评论,一个关于Enum的泛型的例子

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

    专注于协议一致性:

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

    编辑^ 2:

    你甚至可以使用实例变量来使用泛型:

    假设您有一个类和一个实例变量,您希望此实例变量仅采用 ATestClass 类型的值并且符合 ExampleProtocol

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

    然后以这种方式实例化它:

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

    如果 child 不符合协议 ExampleProtocol ,则无法编译

  • 23

    来自ObjC的这个方法 Headers :

    - (void)addFilter:(GPUImageOutput<GPUImageInput> *)newFilter { ... }
    

    与Swift中的此 Headers 相同:

    func addFilter<T: GPUImageOutput where T: GPUImageInput>(newFilter: T?) { ... }
    

    两种方法都会接受同一组类

    • 基于 GPUImageOutput 类;和

    • 符合 GPUImageInput 协议;和

    • newFilter 是可选的,它可以是 nil ;

相关问题