代码之家  ›  专栏  ›  技术社区  ›  Steve Harrison

Objective-C中的属性和实例变量

  •  55
  • Steve Harrison  · 技术社区  · 15 年前

    我对Objective-C中的属性和实例变量相当困惑。

    我大概已经完成了Aaron Hillegas的“MacOSX的可可编程”,一切都是合乎逻辑的。您将声明一个类,如下所示:

    @class Something;
    
    @interface MyClass : NSObject {
        NSString *name;
        NSArray *items;
    
        Something *something;
    
        IBOutlet NSTextField *myTextField;
    }
    
    @property (nonatomic, retain) NSString *name;
    @property (nonatomic, retain) NSArray *items;
    
    • 因为其他物体需要操纵 name items 实例变量,我们使用 @property / @synthesize 为它们生成访问器/转换器。在我们的类中,我们不使用访问器/变异器,我们只是直接与实例变量交互。

    • something 只是我们将在类中使用的一个实例变量,由于没有其他人需要使用它,所以我们不会为它创建一对访问器和赋值器。

    • 我们需要与UI中的文本字段交互,因此我们声明 IBOutlet 为了它,连接它,我们就完成了。

    一切都很合乎逻辑。

    然而,在iPhone世界里,情况似乎有所不同。人们为每个实例变量声明属性,为 IBOutlets ,并使用访问器/转换器与实例变量交互 在内部 课程(例如他们会写 [self setName:@"Test"] 而不是 name = @"Test" )

    为什么?怎么回事?这些差异是iPhone特有的吗?为所有实例变量声明属性和为其声明属性有什么好处 伊布斯特 以及在自己的类中使用访问器/转换器?

    5 回复  |  直到 11 年前
        1
  •  29
  •   Mehrdad Afshari    15 年前

    在iPhone世界里,没有垃圾收集器。你必须通过引用计数来小心地管理内存。考虑到这一点,考虑以下两者之间的区别:

    name = @"Test";
    

    self.name = @"Test";
    // which is equivalent to:
    [self setName: @"Test"];
    

    如果直接设置实例变量,而不事先考虑,将丢失对前一个值的引用,并且无法调整其保留计数(应该 release d手动)。如果您通过属性访问它,它将自动为您处理,同时增加新分配对象的保留计数。

    基本概念不是针对iPhone的,但在没有垃圾收集器的环境中,它变得至关重要。

        2
  •  6
  •   stefanB    15 年前

    属性用于为实例变量生成访问器,不会发生任何魔力。

    您可以手动实现相同的访问器。

    你可以在Aaron Hillegass的书中找到成员变量的3种记忆管理策略的例子。他们是 assign/copy/retain . 您可以根据给定变量的需要选择其中一个变量。

    我假设你理解客观C中的记忆管理…

    访问器隐藏每个变量的内存管理的复杂性和差异。

    例如:

    name = @"Test"
    

    是一个简单的任务, name 现在引用 NSString @"Test" . 但是你可以决定使用 copy retain . 无论选择哪个版本的内存管理,访问器都隐藏了复杂性,并且始终使用(或类似的)访问变量:

    [self setName:@"Test"] 
    [self name]
    

    现在 setName: 可能使用 assign/copy or retain 你不用担心。

    我的猜测是,iPhone教程使用属性使新开发人员更容易跳过内存管理(即使用属性生成适当的访问器,而不是每次都用手工实现这些访问器也很方便)。

        3
  •  3
  •   Peter Hosey    15 年前

    然而,在iPhone世界里,情况似乎有所不同。人们为每个实例变量声明属性,为 IBOutlets ,并使用访问器/转换器与类中的实例变量进行交互(例如,它们将写入 [self setName:@"Test"] 而不是 name = @"Test" )。

    这不是iPhone特有的。除了在 init 方法与 dealloc 方法,最好始终使用访问器。主要的好处,特别是在Mac上(使用cocoa绑定),是使用访问器意味着免费的kvo通知。

    人们为每个实例变量声明属性的原因很可能是他们的所有实例变量都是他们希望作为属性公开的东西。如果他们有一些想要保密的东西,他们不会在头文件中声明它的属性。(但是,他们可以在实现文件的类扩展名中为其创建一个属性,以便获得上述免费的kvo通知。)

    在我看来,为销售点申报房产是多余的。我看不出有什么意义。如果不创建属性,NIB加载器将通过直接实例变量访问来设置出口,这对于该任务来说很好。

        4
  •  2
  •   JRT    14 年前

    我建议,现代发展已经作出了非常强烈的尝试,以确定、定义和应用最佳实践。

    在这些最佳实践中,我们发现了连续性和一致性。

    除了在 init dealloc 方法、访问器通常应始终(类内和类外)用于它们提供的好处,包括 encapsulation ,多态的var实现(都允许抽象和重构),并促进连续性和一致性的最佳实践。当以这种方式做事情并充分利用语言能力时,面向对象语言的基本好处就会发挥出来。正如任何高级程序员通常会证明的那样,在编码中总是保持一致是一个经常被提到的好处。

        5
  •  0
  •   Shafraz Buhary    11 年前

    你可以这样写

    //MyClass.h
    
    @class Something;
    
    @interface MyClass : NSObject 
    
    @property (nonatomic, strong) NSString *name;
    @property (nonatomic, strong) NSArray *items;
    
    @end 
    
    //MyClass.m
    @interface MyClass() 
    
    @property (nonatomic, strong) IBOutlet NSTextField *myTextField;
    @property (nonatomic, strong) Something *something;
    
    @end