Função que usa um protocolo e uma instância de classe (!) Conforme como parâmetros
Estou tentando descobrir como definir uma função que usa os dois parâmetros a seguir:
Um protocoloUma instância de umclasse (umatipo de referência) em conformidade com esse protocolo.Por exemplo, dado
protocol P { }
class C : P { } // Class, conforming to P
class D { } // Class, not conforming to P
struct E: P { } // Struct, conforming to P
isso deve compilar:
register(P.self, obj: C()) // (1)
mas estes não devem compilar:
register(P.self, obj: D()) // (2) D does not conform to P
register(P.self, obj: E()) // (3) E is not a class
É fácil descartar a condição de que o segundo parâmetro seja uma instância de classe:
func register<T>(proto: T.Type, obj: T) {
// ...
}
mas isso aceitaria a estrutura (tipo de valor) em(3)
também. Isso parecia promissor e compila
func register<T: AnyObject>(proto: T.Type, obj: T) {
// ...
}
mas então nenhum(1)
, (2)
, (3)
compile mais, por exemplo
register(P.self, obj: C()) // (1)
// error: cannot invoke 'register' with an argument list of type '(P.Protocol, obj: C)'
I presumir que o motivo do erro do compilador é o mesmo que emProtocolo não se conforma a si mesmo?.
Outra tentativa fracassada é
func register<T>(proto: T.Type, obj: protocol<T, AnyObject>) { }
// error: non-protocol type 'T' cannot be used within 'protocol<...>'
Uma alternativa viável seria uma função que toma como parâmetros
A classe protocolo.Uma instância de um tipo em conformidade com esse protocolo.Aqui, o problema é como restringir o primeiro parâmetro, de modo que apenas protocolos de classe sejam aceitos.
Fundo: Eu tropecei recentementeSwiftNotificationCenter projeto que implementa um mecanismo de notificação segura do tipo orientado a protocolo. Tem umregister
método que se parece com isso:
public class NotificationCenter {
public static func register<T>(protocolType: T.Type, observer: T) {
guard let object = observer as? AnyObject else {
fatalError("expecting reference type but found value type: \(observer)")
}
// ...
}
// ...
}
Os observadores são armazenados como referências fracas, e é por isso que eles devem ser tipos de referência, ou seja, instâncias de uma classe. No entanto, isso é verificado apenas no tempo de execução, e eu me pergunto como fazer uma verificação em tempo de compilação.
Estou perdendo algo simples / óbvio?