【问题标题】:The Field between Objective-c and Java, and I don't understand the @property and instance variableObjective-c和Java之间的Field,我不明白@property和实例变量
【发布时间】:2014-01-10 07:21:23
【问题描述】:

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

1.

 @interface Person : NSObject

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

 @end

2.

  @interface Person : NSObject{

    NSString *firstName;
    NSString *lastName;
  }

 @end

使用Java-Language,我们定义了两个字符串字段:

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

当从另一个类或方法或函数中的任何其他代码访问公共实例变量时,使用 -> 指针运算符表示法。因此,您可以访问 C++/C 中的 Public Filed,如下所示:

  [[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是否等价于实例变量?

【问题讨论】:

  • 前两天开始学习Objective-C。
  • 看看这个 SO 问题link
  • 我看过,但我什至不明白。
  • 您不再需要使用数字 2。它已经过时了。
  • 天哪! Objective-C的setter和getter机制与C#类似

标签: objective-c cocoa


【解决方案1】:

让我们从(2)开始

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

在这种情况下,firstNamelastName 被称为 ivarsInstance Variables,我通常不会声明 ivars。一些开发人员现在说您不应该将这些放在@interface 声明中,原因有两个。

  1. 它向类的用户公开有关实现的详细信息,这将导致其他开发人员或使用以及在某些情况下您自己依赖他们应该可用的实现细节。

  2. 一些开发人员认为将这些放在@interface 中可以显着延长编译时间。

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

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

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

在Java中等价于private String firstName;


现在让我们看看(1)

@interface Person : NSObject

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

@end

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

通过声明一个属性,您基本上会自动为这些属性生成getterssetters。在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 仍然是私有的,它是我们向其他人开放的 getter 和 setter。


您也错过了第三种选择。由于 Objective-c 中的约定,@property 会发生什么情况?

我们已经将它声明为

 @property (nonatomic) BOOL personForObject; 

在objective-c 中,当涉及到布尔值时,getter 的名称略有不同。虽然我们对

的合成二传手感到满意
- (void)setPersonForObject:(BOOL)aPersonForObject 
{
    self.personForObject = aPersonForObject;
}

虽然我们对 getter 不满意,但对于布尔值,getter 应该以 is 开头,所以 personForObjects getter 应该是 isPersonForObject 但合成器不知道这一点,因此会自动生成反之亦然。所以我们需要在属性声明中告诉它

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

你现在必须自己实现这个方法

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

请注意,只有在您选择忽略我不推荐的约定时才需要这样做。

任何问题都可以问。

【讨论】:

  • 吃点菠菜。那是最好的描述。感谢在接口与实现中调用 ivars。
  • 小错字伙伴。您不能持有对 BOOLstrong 引用,因为它不是对象。
  • @uchuugaka 实际上我在工作的时候已经没时间了,但我也打算详细说明如何调用它们。
  • 我需要花费一些时间来消化你的答案,如果你的答案是正确的,我会纠正你!感谢您的详细回答!不胜感激!
  • 今天花了很多时间研究Objective-C,稍后我会问一些关于这个主题的问题。非常感谢。 @大力水手
【解决方案2】:

第二个代码相当于 Java 版本。

最完整版本中的@property 定义了getter、setter 和实例变量。您还可以修改声明以仅指定 getter、仅指定 setter 或指定不同的实例变量。

【讨论】:

    【解决方案3】:

    @property 是定义实例变量及其对应访问器的简写。 如果只是在接口中定义实例变量,是不会得到访问器方法的。

    【讨论】:

      【解决方案4】:

      看看每当你在 Objective-C 中声明成员时,你应该为这些成员(变量)提供 getter 和 setter。但是 Objective-C 使用指令 @property@synthesize 支持称为 synthesized accessors 的东西。

      现在让我们看看带有合成访问器的程序:

      #import<Foundation/Foundation.h>
      @interface Person : NSObject{
      NSString * firstName;// declaring that Person class as variable firstName
      NSString * lastName;// // declaring that Person class as variable lastName
      }
      
      @property NSString *firstName; // says to compiler that we want to define synthesized accesor for the firstName
      @property NSString *lastName;// says to compiler that we want to define synthesized accesor for the lastName
      @end
      
      @implementation Person
      
      @synthesize firstName, lastName;// synthesized accessor to be defined for firstName and lastName
      
      @end;
      
      int main(){
          NSAutoreleasePool * pool = [[NSAutoreleasePool alloc]init];
          Person * p = [[Person alloc]init] ;
          [p setFirstName:@"Yogish"]; // method setFirstName is implicitly defined by compiler
          [p setLastName:@"Gowda"];// method setLastName is implicitly defined by compiler
          NSLog(@"%@",p.firstName);
          NSLog(@"%@",p.lastName);
          [pool drain];
          return 0;
      
          }
      

      现在回来,如果你还没有使用过 @property@synthesize 你应该编写自己的 setter 和 getter 方法设置和获取成员 firstName 和 lastName。由于您使用的是@property 和@synthesize,编译器将编写getter 和setter 方法。

      希望这会有所帮助:)

      【讨论】:

      • 你定义了 firstName 和 lastName 两次?或者只是相同的变量
      • 我没有定义 firstName 和 lastName 两次。用 cmets 查看编辑后的答案。我
      • 大部分代码已经过时了,因此比有用的 imo 更令人困惑
      • @wyf 请通过此链接您可能会得到更好的想法Synthesized accesors。 :)
      • @iamyogish 虽然是的,但它是正确的,但它确实已经过时了,对于您的答案,不需要ivars@synthesize,除非您使用的是xcode 的版本这是古老的@synthesize 是自动为您完成的,ivars 也是如此,这些现在是为属性自动创建的。如果您检查页面底部的最后修改以获取您提供的链接,则该链接已过期近 2 年。虽然它是正确的并且仍然可以这样做,但它也是不正确的,因为这样做真的没有意义。
      猜你喜欢
      • 2012-03-10
      • 2010-12-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-02
      • 2023-04-04
      • 1970-01-01
      • 2013-05-15
      相关资源
      最近更新 更多