什么是 NSObject<Protocol> 的 swift 等价物?
Posted
技术标签:
【中文标题】什么是 NSObject<Protocol> 的 swift 等价物?【英文标题】:whats the swift equivalent of NSObject<Protocol>? 【发布时间】:2015-08-11 17:51:00 【问题描述】:我有一个类需要使用 NSObject 子类的变量进行设置,并且实现了某个协议。
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'
在上面的例子中,变量的声明都不起作用。因为他们都不知道基类?
如何快速实现这一点?
【问题讨论】:
【参考方案1】:通常相当于 Swift 中的NSObject<Protocol>
就是Protocol
。通常,这个协议被声明为一个类协议,以保证它会被一个类所采用。
如果你还需要NSObject协议方法(比如respondsToSelector:
,那么让Protocol采用NSObjectProtocol。
如果问题仅仅是你想调用copy()
而你无法说服编译器让你这样做,那么也采用NSCopying(或者只是使用respondsToSelector:
和performSelector:
绕过编译器完全)。
【讨论】:
【参考方案2】:您可以通过多种方式做到这一点。首先,您可以将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
属于不同类型,您的问题我有点不清楚。如果您确实希望它们是不同的类型,我可以在此答案中添加其他建议。
【讨论】:
谢谢 Roman,所以你认为没有办法在变量声明中强制执行 NSObject 吗? 您可以将变量定义为var protoInstance: NSObject?
,然后在您想使用它时转换为Prototest
。但是如果你想强制该属性既是NSObject
和 Prototest
,那么你将不得不在某处使用泛型......
@EdwardAshak “所以你认为没有办法强制执行 NSObject” 为什么你认为你需要这样做?
对所有init
方法施加通用约束可确保变量仅使用NSObject
类型进行初始化。因此,即使变量不限于NSObject
,实际上您也可以始终转换为NSObject
,并确保转换成功。
这个变量被初始化为AClass类型的对象,它是NSObject的子类并实现了协议。我允许将变量设置为与定义中的 AClass 等效的任何对象,该对象在某些时候也被视为 NSObject。我希望这能澄清一点以上是关于什么是 NSObject<Protocol> 的 swift 等价物?的主要内容,如果未能解决你的问题,请参考以下文章