protocolos multiple herencia swift

multiple - ¿Cómo especifico que un tipo Swift no genérico debe cumplir con un protocolo?



protocolos swift (2)

Me gustaría implementar un método Swift que tome un determinado tipo de clase, pero solo tome instancias de aquellas clases que cumplan con un protocolo específico Por ejemplo, en Objective-C tengo este método:

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

donde GPUImageOutput es una clase particular, y GPUImageInput es un protocolo. Solo GPUImageOutput clases GPUImageOutput que cumplen con este protocolo son entradas aceptables para este método.

Sin embargo, la versión Swift automática generada de lo anterior es

func addFilter(newFilter: GPUImageOutput!)

Esto elimina el requisito de que GPUImageOutput clases GPUImageOutput cumplan con el protocolo GPUImageInput , lo que permitirá que se pasen objetos no conformes (y luego se bloqueen en tiempo de ejecución). Cuando intento definir esto como GPUImageOutput<GPUImageInput> , el compilador GPUImageOutput<GPUImageInput> un error de

No se puede especializar el tipo no genérico ''GPUImageOutput''

¿Cómo haría esta clase de especialización y protocolo en un parámetro en Swift?


Es rápido debes usar genéricos, de esta manera:

Dadas estas declaraciones de ejemplo de protocolo, clase principal y subclase:

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

Ahora, desea definir un método que tome parámetros de entrada de tipo ATestClass (o un elemento secundario) que cumpla con el protocolo ExampleProtocol. Escribe la declaración del método de esta manera:

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

Tu método, redefinido en veloz, debería ser

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

EDITAR:

como su último comentario, un ejemplo con genéricos en un Enum

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

Especializado en conformidad con el protocolo:

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

EDICIÓN ^ 2:

Puedes usar genéricos incluso con variables de instancia:

Digamos que tiene una clase y una variable de instancia, desea que esta variable de instancia solo tome valores del tipo ATestClass y que se ajuste a ExampleProtocol

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

Luego ejemplifícalo de esta manera:

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

Si el child no cumple con el protocolo ExampleProtocol , no compilará


este encabezado de método de ObjC:

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

es idéntico a este encabezado en Swift :

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

Ambos métodos aceptarán el mismo conjunto de clases.

  • que se basa en la clase GPUImageOutput ; y
  • cumple GPUImageInput protocolo GPUImageInput ; y
  • el newFilter es opcional, puede ser nil ;