代码之家  ›  专栏  ›  技术社区  ›  Todd Ditchendorf

+initialize/+load是否应该始终以:if(self==[MyClass])保护开始?

  •  10
  • Todd Ditchendorf  · 技术社区  · 17 年前

    从这种守卫开始

    @implementation MyClass
    
    + (void)initialize {
        if (self == [MyClass class]) {
            ...
        }
    }
    
    ...
    @end
    

    似乎+load和+initialize中的代码通常只希望执行一次。因此,这将有助于避免在加载/初始化子类时重复执行。

    我想我只是想从一些ObjC向导那里得到一些加强,这是必要的/常见的实践。。。

    在这个问题上有什么共同的看法?你会建议一直这样做吗?

    对于+load和+initialize,您的建议是相同的,还是在处理它们的方式上存在差异?

    谢谢

    3 回复  |  直到 17 年前
        1
  •  5
  •   James Eichele Bernard Igiri    17 年前

    in-depth discussion of this matter 可以在苹果开发者邮件列表中找到。

    1. 运行时将实际调用 +initialize 关于超类 之前
    2. 如果你 包括guard,类的子类,它们有自己的 +初始化 方法将不会触发依赖的KVO通知。

    有关第2点的示例,请务必阅读 this post

        2
  •  4
  •   Matt Gallagher    17 年前

    也就是说,在很多情况下,你可以避免它。。。

    如果需要对每个类的每个继承人执行工作,则不应使用此条件结束:

    • 编辑添加:

    在有些情况下,你不必费心:

    • 如果执行的操作是幂等的(如果重复,则不要更改值)
    • 该类是“密封的”(设计上没有后代)

    “幂等元”部分是相关的。初始值设定项应该只是设置初始状态(每次都应该相同)。在一个好的初始化器中,重复应该不重要。虽然我想如果你忘记在条件中包装这个方法 不管怎样,这可能很烦人。

    另一种方法是测试要初始化的属性是否已经初始化,这种方法可以正确地反映任何只初始化一次的需求。即

    id myGlobalObject = nil;
    
    +(void)initialize
    {
        if (myGlobalObject == nil)
        {
            myGlobalObject = [[MyGlobalClass alloc] init];
        }
    }
    
        3
  •  1
  •   Lings    12 年前

    因为类的initialize方法可能会被多次调用。e、 g.当您在父类中实现初始化,而不在子类中实现时,那么您首先调用子类,父类的初始化将被调用两次。

    @implementation BaseClass
    
    + (void)initialize
    {
        NSLog(@"BaseClass initialize self=%@, class=%@", self, [BaseClass class]);
    }
    
    @end
    
    @interface SubClass : BaseClass
    @end
    
    @implementation SubClass
    
    // don't implement the initialize method
    
    @end
    

    ==================

    现在,当您首先调用子类时,就像

    [SNSBaseSubLogic alloc]
    

    查看调试控制台,输出:

    BaseClass initialize self=BaseClass, class=BaseClass
    BaseClass initialize self=SubClass, class=BaseClass
    

    所以,你必须使用

    + (void)initialize
    {
       if (self == [BaseClass class]) {
          NSLog(@"BaseClass initialize self=%@, class=%@", self, [BaseClass class]);
       }
    }