来自前两天开始学习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
在这种情况下,firstName
和lastName
对我来说被称为ivars
或实例变量
,我不知道通常声明ivars
。现在,一些开发人员表示,出于两个原因,您不应将这些内容放入 @interface
声明中。
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.
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
会在后台自动声明。
通过声明属性,您基本上会自动为这些属性生成 getter
和 setter
。在 xcode
的早期版本中,您确实必须 @synthesize
但不再需要这样做了。因此,声明两个属性 firstName
和 lastName
这将在后台生成
- (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/