-init
和+initialize
是完全不同的东西。第一个是用于初始化实例; 第二个是用于初始化类。
每次消息发送到某个给定的类时,运行时都会确保在它及其超类上调用+initialize
。由于任何子类在初始化自身之前需要准备好其超类,因此先初始化超类。
因此,第一次发送到YourSubclass
的时间,运行时可能会执行以下操作:
[NSObject initialize]
[YourClass initialize]
[YourSubclass initialize]
(虽然这很不可能是第一次发送消息给NSObject
,所以可能在这一点上它不需要被初始化。这只是为了说明问题。)
如果YourSubclass
没有实现+initialize
,那么上面显示的[YourSubclass initialize]
调用实际上会调用+[YourClass initialize]
。这就是正常的继承机制起作用。这将导致+[YourClass initialize]
第二次被调用。
由于+initialize
方法中所做的工作通常是只应该做一次的事情,因此需要使用保护条件if (self == [TheClassWhoseImplementationThisMethodIsPartOf class])
。此外,这项工作通常假定self
指的是当前编写的类,因此也是保护条件的原因。
你引用的第二个答案指出了一个例外情况,即使用旧的机制通过+setKeys:triggerChangeNotificationsForDependentKey:
方法注册KVO依赖键。该方法仅适用于实际调用它的类,而不适用于任何子类。你应该避免使用它,并使用更现代的+keyPathsForValuesAffectingValueForKey:
或+keyPathsForValuesAffecting<Key>
方法。如果必须使用旧方式,请将该部分放在保护条件外面。此外,这样的类的子类必须调用super
,这通常不会做。
更新:
+initialize
方法通常不应调用super
,因为运行时已经初始化了超类。只有当超类已知使用旧机制注册依赖键时,任何子类都必须调用super
。
与此相反,在-init
的情况下不存在同样的担忧,因为运行时不会在调用你的方法之前自动调用超类的init方法。实际上,如果你的init方法没有调用super
,那么没有东西会初始化实例的超类“部分”。
-init
方法中,你有self = [super init];
这一行代码,它会调用父类的+initialize
方法,我说的对吗? - makaed