objective-c - Objective-c和Java之间的Field,我不明白@property和实例变量

标签 objective-c cocoa

来自前两天开始学习objective-c的开发者,不太明白以下两种方法的区别:

1.

 @interface Person : NSObject

   @property NSString *firstName;
   @property NSString *lastName;

 @end

2.

  @interface Person : NSObject{

    NSString *firstName;
    NSString *lastName;
  }

 @end

使用Java语言,我们定义两个字符串字段:

class Person extends Object{
  (public/private/protected) String firstName;
  (public/private/protected) String lastName;
}

我想知道哪一个(1和2之间)与上面的Java代码具有相同的含义。

<小时/>

非常感谢@iamyogish @Popeye,如果我的答案是正确的,我会纠正你们俩。 阅读电子书《Objective-C 2.0 Essentials》后,我了解到(如果不对,请告诉我。):

@interface Person : NSObject

   @property NSString *firstName;
   @property NSString *lastName;

 @end

这相当于 Java 代码:

class Person extends Object{
 private  String firstName;
 private String lastName;//In fact:private should be protected
 //setter and getter.
 //you can use ecplise tool to generate setter/getter method automaticly
}

正如您可能想象的那样,必须为大量(1000 个或更多)的复杂类编写这些方法最终将被证明是非常耗时的。 Objective-C 提供了综合访问器方法,因此您应该使用 @property 和 @synthesize 指令。如果您像这样编写代码:

@interface Person : NSObject

    NSString *firstName;//note that the default access level is protected.
    NSString *lastName;

 @end

不幸的是,你需要提供可以访问实例变量的方法,例如(你可以自己定义函数的名称)

-(NSString ) getFirstName;
-(NSString ) getLastName;
-(void) setFirstName:(NSString * name);
-(void) setLastName:(NSString * name);

除此之外,如果使用@property和@synthesize指令,您可以像C++/JAVA语法点符号一样访问实例变量,例如:

 NSString * firstName= [[Person alloc] init].firstName;

请注意:理解点表示法的一个关键点是它仅适用于已声明合成访问器方法的实例变量。

实例变量的访问级别是在类声明的 @interface 部分使用 @protected、@private 和 @public 指令指定的。

 @interface Person : NSObject
 @public
    NSString *firstName;//note that the default access level is protected.
    NSString *lastName;

 @end

当从另一个类或方法或函数中的任何其他代码访问公共(public)实例变量时,将使用 -> 指针运算符表示法。因此您可以像这样访问 C++/C 中的公共(public)文件:

  [[Person alloc] init]->firstName = "your first name";

另一个问题是:

  @interface Person : NSObject

   @property NSString *firstName;
   @property NSString *lastName;

 @end

相当于:

@interface Person : NSObject{
   NSString *firstName;
   NSString *lastName;
 }

   @property NSString *firstName;
   @property NSString *lastName;

 @end

还是不? ivar 是否相当于实例变量?

最佳答案

让我们从(2)开始

 @interface Person : NSObject
 {
 NSString *firstName;
 NSString *lastName;
 }
 @end

在这种情况下,firstNamelastName对我来说被称为ivars实例变量,我不知道通常声明ivars。现在,一些开发人员表示,出于两个原因,您不应将这些内容放入 @interface 声明中。

  1. It exposes details about the implementation to users of the class, this will lead other developers who or using and in some cases yourself to rely on implementation details that should be available to them.

  2. Some developers believe that putting these in the @interface can make compile times significantly longer.

大多数开发人员认为,实现 ivar 的最佳方法是在 @implementation 中使用大括号,如下所示:

@implementation Person {
    NSString *firstName;
    NSString *lastName;
}

我们将它们放在这里背后的理论是因为理论上它们被声明为私有(private),除了创建该类的开发人员之外,任何人都无法知道它们。这将解决所有其他开发人员乱搞他们不应该做的事情的问题。

Java 中的等效项就像 private String firstName;

一样简单 <小时/>

现在让我们看一下(1)

@interface Person : NSObject

@property NSString *firstName;
@property NSString *lastName;

@end

从技术上讲,只有当属性需要从其他类访问时才需要使用@properties,但许多开发人员更喜欢使用它们而不是ivars,因为这样更容易访问使用,并且在新版本的 xcode 中,这些属性的 ivars 会在后台自动声明。

通过声明属性,您基本上会自动为这些属性生成 gettersetter。在 xcode 的早期版本中,您确实必须 @synthesize 但不再需要这样做了。因此,声明两个属性 firstNamelastName 这将在后台生成

- (void)setFirstName:(NSString *)aFirstName
{
    self.firstName = aFirstName;
}

- (NSString *)firstName
{ 
    // Note in objective-c we don't generally use `get`
    return self.firstName;
}

- (void)setLastName:(NSString *)aLastName
{
    self.lastName= aLastName;
}

- (NSString *)lastName
{ 
    // Note in objective-c we don't generally use `get`
    return self.lastName;
}

当将其与 Java 进行比较时,这与以下内容非常接近

private String firstName;

public void setFirstName(String aFirstName) {
    this.firstName = aFirstName;
}

public String getFirstName() {
    return this.firstName;
}

我们创建实例变量的方式与普通ivar相同,但是没有什么可说的,在java中创建我的setter和getter,所以我们必须自己做。请注意,java 中的 ivar 仍然是私有(private)的,它是我们向其他人开放的 getter 和 setter。

<小时/>

您还错过了第三种选择。由于 Objective-C 中的约定,使用 @property 作为 bool 会发生什么?

我们将其声明为

 @property (nonatomic) BOOL personForObject; 

在 Objective-C 中,当涉及到 bool 时,getter 的名称略有不同。虽然我们对合成的 setter 感到满意

- (void)setPersonForObject:(BOOL)aPersonForObject 
{
    self.personForObject = aPersonForObject;
}

我们对 getter 不满意,当涉及到 bool 值时,getter 应该以 is 开头,所以 personForObject 的 getter 应该是 isPersonForObject 但合成不知道这一点,因此会以另一种方式自动生成 getter。所以我们需要在属性声明中告诉它,例如

@property (nonatomic, getter=isPersonForObject) BOOL personForObject;

您现在必须自己实现此方法,例如

- (BOOL)isPersonForObject
{
    return self.personForObject;
}

请注意,只有当您选择忽略约定时才需要执行此操作,而我不建议这样做。

有任何问题尽管问。

关于objective-c - Objective-c和Java之间的Field,我不明白@property和实例变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21038337/

相关文章:

objective-c - 为什么这个屏幕尺寸范围是错误的?

objective-c - 将字节序交换为有符号整数的适当方法是什么?

ios - 向 uiview 添加从 A 点移动到 B 点的动画

objective-c - Objective-C 对象可以是它自己的委托(delegate)吗?这是好的编程习惯吗?

c++ - 将 Objective-C 类包装到 C++ 类中 : best practices?

objective-c - 有没有办法更新 launchd overrides.plist 上的 SMLoginItemBookmarks 数据

cocoa - 更改 NSSlider 栏颜色

iphone - Objective C - 实现和扩展之间的区别

objective-c - 在 Objective-C 中,使用派生类的协议(protocol)可以是 "instantiated"吗?

c++ - cocoa Objective-C : use c++ objects as NSDictionary keys?