有人可以解释为什么我们需要在if (self == SomeClass class)
方法中包含+initialize
吗?
我发现了类似的问题(如下所列),但没有找到任何具体的说明:
每个人都说如果你没有在Subclass中实现/覆盖+initialize
,那么它将调用父类两次。
任何人都可以特别解释这一部分,特别是为什么它会两次调用父类?
最后,当我们在继承自NSObject的类中实现+initialize
时,为什么不会发生这种情况,我们在其中创建自定义-init
方法并调用self = [super init];
。
答案 0 :(得分:5)
想象一下,你有一个实现+initialize
的超类和一个没有实现的子类。
@interface SuperClass : NSObject @end
@implementation SuperClass
+(void)initialize {
NSLog(@"This is class %@ running SuperClass +initialize", self);
}
@end
@interface SubClass : SuperClass @end
@implementation SubClass
// no +initialize implementation
@end
使用超类。这引发了对+[SuperClass initialize]
的调用。
[SuperClass class];
=> This is class SuperClass running SuperClass +initialize
现在使用子类。运行时在+initialize
中查找SubClass
的实现,但找不到任何内容。然后它在SuperClass
中查找继承的实现并找到它。即使已经代表SuperClass
本身调用了一次,也会调用继承的实现:
[SubClass class];
=> This is class SubClass running SuperClass +initialize
守卫允许您执行必须最多运行一次的工作。对[{1}}的任何后续调用都有+initialize
不同的类,因此警卫可以忽略它们。
答案 1 :(得分:4)
-init
和+initialize
完全不同。第一个用于初始化实例;第二个用于初始化类。
第一次给出任何给定的类消息时,运行时确保在其上调用{em>及其超类 +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
,那么什么都不会初始化超类的实例的“部分”。
答案 2 :(得分:0)
您引用的问题有很好的接受答案。总而言之,+initialize
由运行时在每个类上调用,因此对于具有N个子类的超类,它将在超类上被调用N + 1次(一次直接,并且每个继承它的子类一次)。如果子类重写它并调用super。
你可以通过询问超类级别来防止这种情况,“这是我的系统直接初始化,而不是'super'被我的子类继承或调用吗?”
if (self == [ThisSuperclass self]) {}
-init
用于初始化类的实例,默认情况下不会被运行时调用,如+initialize
。实例继承了-init的实现,可以覆盖继承的实现,也可以通过调用[super init];
来享受继承实现的好处。