如何继承NSDictionary?

far*_*adf 10 objective-c

我有一个名为Settings的对象,它继承自NSMutableDictionary.当我尝试使用初始化此对象时

Settings *settings = [[Settings alloc] initWithContentsOfFile: @"someFile"]
Run Code Online (Sandbox Code Playgroud)

它返回一个类型的对象NSCFDictionary.因此,它无法识别我的其他方法.例如,当我调用选择器"save"时,它对象:

[NSCFDictionary save]: unrecognized selector sent to instance 0x524bc0
Run Code Online (Sandbox Code Playgroud)

当然,当我使用花园品种初始化时,它是可以的

Settings *settings = [[Settings alloc] init]
Run Code Online (Sandbox Code Playgroud)

我试图将它再次投射到设置,但这不起作用.这看起来很简单 - 我错过了什么?

谢谢

Chu*_*uck 18

NSDictionary是一个类集群.这意味着从其init方法返回的值不是严格意义上的NSDictionary,而是实现实际功能的子类.几乎在每种情况下,最好为您的类提供一个NSDictionary作为实例变量,或者只是在NSDictionary上定义一个类别.


Qui*_*lor 16

Chuck对于NSDictionary(和Dave,扩展名,关于NSArray/Set/String)和类集群是正确的.-[NSDictionary initWithContentsOfFile:]可能性是调用不同的初始化程序-init,这就是为什么它将分配的Settings实例换成另一个NSMutableDictionary的子类.(从文件读取时的初始化操作可以选择NSDictionary的特定已知子类,它可以很好地从文件中加载,等等)

我会回应Chuck的指导,使用组合或类别而不是继承NSDLictionary 几乎总是更好.您很可能以更简单的方式完成类别操作,并在此过程中减少潜在的错误.在决定继承之前,请考虑自己警告.

话虽如此,NSDictionary和NSMutableDictionary都被设计为支持子类化,并且在极少数情况下这是正确的事情.在尝试之前,请仔细考虑它.如果您发现它是您设计的正确选择,请按照以下要求了解并执行以下操作:

  1. NSDictionary重写以下基本方法:
    • -count
    • -objectForKey:
    • -keyEnumerator
    • -initWithObjects:forKeys:count:(指定初始化程序)
  2. NSMutableDictionary重写以下基本方法:
    • -setObject:forKey:
    • -removeObjectForKey:
  3. 如果您支持NSCoding,请注意classForKeyedArchiverreplacementObjectForKeyedArchiver:(来自NSObject的实例方法) - 它们可以完全改变您的类的响应方式,并且您经常无意中从NS(Mutable)Dictionary继承一些奇怪的行为.(您可以通过在它们上设置断点来验证它们是否是罪魁祸首,或者实现它们以调用超级并破坏您自己的代码.)

我已经在我自己的NSMutableDictionary子类中实现了许多这些点.您可以查看并使用代码,但可能对您有所帮助.特别帮助我(可能是你的问题的解决方案)的一个是重载指定的初始化程序,该程序目前没有记录(雷达#7046209).

要记住的是,尽管这些子弹涵盖了最常见的用途,但总会有边缘情况和不常见的功能需要考虑.例如,-isEqual:-hash用于测试平等,等