如何指定非泛型 Swift 类型应遵守协议? [英] How do I specify that a non-generic Swift type should comply to a protocol?
问题描述
我想实现一个 Swift 方法,该方法接受某种类类型,但只接受符合特定协议的那些类的实例.例如,在 Objective-C 中我有这个方法:
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;
其中 GPUImageOutput
是一个特定的类,而 GPUImageInput
是一个协议.只有符合此协议的 GPUImageOutput
类才是此方法可接受的输入.
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.
然而,上面自动生成的Swift版本是
However, the automatic Swift-generated version of the above is
func addFilter(newFilter: GPUImageOutput!)
这消除了 GPUImageOutput
类遵守 GPUImageInput
协议的要求,这将允许传入不合规的对象(然后在运行时崩溃).当我尝试将其定义为 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
不能特化非泛型类型 'GPUImageOutput'
Cannot specialize non-generic type 'GPUImageOutput'
我将如何在 Swift 中的参数中进行这样的类和协议特化?
How would I do such a class and protocol specialization in a parameter in Swift?
推荐答案
你必须快速使用泛型,这样:
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")
}
}
现在,您要定义一个方法,该方法采用符合 ExampleProtocol 协议的 ATestClass(或子项)类型的输入参数.像这样编写方法声明:
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)
}
你的方法,在 swift 中重新定义,应该是
Your method, redefined in swift, should be
func addFilter<T where T:GPUImageOutput, T:GPUImageInput>(newFilter:T!)
{
// ...
}
作为你最后的评论,一个关于枚举的泛型示例
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)
专注于协议一致性:
enum OptionalValue<T where T:GPUImageOutput, T:GPUImageInput> {
case None
case Some(T)
}
编辑^2:
您甚至可以使用实例变量使用泛型:
you can use generics even with instance variables:
假设你有一个类和一个实例变量,你希望这个实例变量只接受 ATestClass
类型的值并且符合 ExampleProtocol
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?
}
然后这样实例化:
var child = ATestClassChild()
let aGen = GiveMeAGeneric<ATestClassChild>()
aGen.aGenericVar = child
如果child
不符合ExampleProtocol
协议,则不会编译
If child
doesn't conform to the protocol ExampleProtocol
, it won't compile
这篇关于如何指定非泛型 Swift 类型应遵守协议?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!