Функция, принимающая в качестве параметров протокол и экземпляр соответствующего класса (!)
Я пытаюсь выяснить, как определить функцию, которая принимает следующие два параметра:
Протокол.Экземпляручебный класс (атип ссылки) в соответствии с этим протоколом.Например, учитывая
protocol P { }
class C : P { } // Class, conforming to P
class D { } // Class, not conforming to P
struct E: P { } // Struct, conforming to P
это должно скомпилировать:
register(P.self, obj: C()) // (1)
но они не должны компилироваться:
register(P.self, obj: D()) // (2) D does not conform to P
register(P.self, obj: E()) // (3) E is not a class
Это легко, если мы отбросим условие, что второй параметр является экземпляром класса:
func register<T>(proto: T.Type, obj: T) {
// ...
}
но это будет принимать структуру (тип значения) в(3)
также. Это выглядело многообещающе и компилирует
func register<T: AnyObject>(proto: T.Type, obj: T) {
// ...
}
но тогда ни один из(1)
, (2)
, (3)
компилировать больше, например
register(P.self, obj: C()) // (1)
// error: cannot invoke 'register' with an argument list of type '(P.Protocol, obj: C)'
I предполагать что причина ошибки компилятора такая же, как вПротокол не соответствует самому себе?.
Еще одна неудачная попытка
func register<T>(proto: T.Type, obj: protocol<T, AnyObject>) { }
// error: non-protocol type 'T' cannot be used within 'protocol<...>'
Жизнеспособной альтернативой будет функция, которая принимает в качестве параметров
A учебный класс протокол.Экземпляр типа, соответствующего этому протоколу.Здесь проблема заключается в том, как ограничить первый параметр так, чтобы были приняты только протоколы классов.
Фон: Я недавно наткнулся наSwiftNotificationCenter проект, который реализует ориентированный на протокол, механизм безопасного уведомления типа. Оно имеетregister
метод, который выглядит так:
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)")
}
// ...
}
// ...
}
Затем наблюдатели сохраняются как слабые ссылки, и поэтому они должны быть ссылочными типами, то есть экземплярами класса. Однако, это проверяется только во время выполнения, и мне интересно, как сделать это во время компиляции.
Я пропускаю что-то простое / очевидное?