NSObject<Protocol> 的 swift 等价物是什么?
whats the swift equivalent of NSObject<Protocol>?
我有一个 class 需要设置一个 NSObject 子变量 class 并且它实现了某个协议。
protocol ProtoTest {
var foo: Int { get set }
}
class AClass: NSObject, ProtoTest {
var foo: Int = 3
}
class BClass: NSObject, ProtoTest {
var foo: Int = 4
}
class Consumer {
var protoInstance: ProtoTest? //Does not cary any information of the class just the protocol
var protoInstance2: protocol<NSObjectProtocol, ProtoTest>?
init(x: ProtoTest) {
self.protoInstance = x
self.protoInstance2 = nil
}
init(x: protocol<NSObjectProtocol, ProtoTest>) {
self.protoInstance2 = x
self.protoInstance = nil
}
func doSomething() {
if let x = protoInstance {
x.copy() //'ProtoTest' does not have a member named 'copy'
}
if let x = protoInstance2 {
x.copy() //protocol<NSObjectProtocol, ProtoTest> does not have a member named 'copy'
}
}
}
在上面的例子中,变量的声明都不起作用。因为他们都不知道基数 class?
如何在 swift 中实现它?
您可以通过多种方式完成此操作。首先,您可以使 Consumer
通用:
class Consumer<T: NSObject where T: Prototest> {
var protoInstance: T?
var protoInstance2: T?
}
如果这样做,那么所有对 protoInstance
或 protoInstance2
的引用都将从 NSObject
继承,您将能够直接调用 .copy()
等方法对象。
如果您不希望 Consumer
是通用的,您可以使用通用参数对 init
方法施加限制,如下所示:
class Consumer {
// ...
init<T: NSObject where T: Prototest>(x: T) {
protoInstance = x
}
}
如果你这样做,你将保证 protoInstance
将是一个 NSObject
,但你必须转换为 NSObject
才能使用任何 NSObject
的方法:
func doSomething() {
if let x = protoInstance as? NSObject {
x.copy()
}
}
编辑:
请注意,我不确定您是否真的希望 protoInstance
和 protoInstance2
是不同的类型 我对您的问题有点不清楚。如果您确实希望它们是不同的类型,我可以在此答案中添加其他建议。
通常 相当于 Swift 中的 NSObject<Protocol>
就是 Protocol
。通常,此协议声明为 class 协议 以保证它将被 class.
采用
如果你还需要NSObject的协议方法(比如respondsToSelector:
,那就让Protocol采用NSObjectProtocol。
如果问题仅仅是你想调用 copy()
而你不能说服编译器让你这样做,那么也采用 NSCopying(或者只使用 respondsToSelector:
和 performSelector:
完全绕过编译器)。
我有一个 class 需要设置一个 NSObject 子变量 class 并且它实现了某个协议。
protocol ProtoTest {
var foo: Int { get set }
}
class AClass: NSObject, ProtoTest {
var foo: Int = 3
}
class BClass: NSObject, ProtoTest {
var foo: Int = 4
}
class Consumer {
var protoInstance: ProtoTest? //Does not cary any information of the class just the protocol
var protoInstance2: protocol<NSObjectProtocol, ProtoTest>?
init(x: ProtoTest) {
self.protoInstance = x
self.protoInstance2 = nil
}
init(x: protocol<NSObjectProtocol, ProtoTest>) {
self.protoInstance2 = x
self.protoInstance = nil
}
func doSomething() {
if let x = protoInstance {
x.copy() //'ProtoTest' does not have a member named 'copy'
}
if let x = protoInstance2 {
x.copy() //protocol<NSObjectProtocol, ProtoTest> does not have a member named 'copy'
}
}
}
在上面的例子中,变量的声明都不起作用。因为他们都不知道基数 class?
如何在 swift 中实现它?
您可以通过多种方式完成此操作。首先,您可以使 Consumer
通用:
class Consumer<T: NSObject where T: Prototest> {
var protoInstance: T?
var protoInstance2: T?
}
如果这样做,那么所有对 protoInstance
或 protoInstance2
的引用都将从 NSObject
继承,您将能够直接调用 .copy()
等方法对象。
如果您不希望 Consumer
是通用的,您可以使用通用参数对 init
方法施加限制,如下所示:
class Consumer {
// ...
init<T: NSObject where T: Prototest>(x: T) {
protoInstance = x
}
}
如果你这样做,你将保证 protoInstance
将是一个 NSObject
,但你必须转换为 NSObject
才能使用任何 NSObject
的方法:
func doSomething() {
if let x = protoInstance as? NSObject {
x.copy()
}
}
编辑:
请注意,我不确定您是否真的希望 protoInstance
和 protoInstance2
是不同的类型 我对您的问题有点不清楚。如果您确实希望它们是不同的类型,我可以在此答案中添加其他建议。
通常 相当于 Swift 中的 NSObject<Protocol>
就是 Protocol
。通常,此协议声明为 class 协议 以保证它将被 class.
如果你还需要NSObject的协议方法(比如respondsToSelector:
,那就让Protocol采用NSObjectProtocol。
如果问题仅仅是你想调用 copy()
而你不能说服编译器让你这样做,那么也采用 NSCopying(或者只使用 respondsToSelector:
和 performSelector:
完全绕过编译器)。