简体   繁体   English

这三种声明变量的方式有什么区别?

[英]What is the difference between these three ways to declare a variable?

I am learning Objective-C and was just curious. 我正在学习Objective-C,只是好奇。 I can create an object of a NSString in these places, and please provide any others. 我可以在这些地方创建一个NSString对象,请提供其他对象。 To me they all do the same thing. 对我来说,他们都做同样的事情。 I don't know what is the difference is between them. 我不知道它们之间有什么区别。 Where is it stored? 它存储在哪里? From where can I access it? 从哪里可以访问它? What are the advantages? 有什么优势?

1) 1)

// .h
@interface ...
@property (strong,nonatomic) NSString *text;
@end

2) 2)

// .h
@interface ... { 
NSString *text
}
@end

3) 3)

// .m
@interface ... ()
@property (strong,nonatomic) NSString *text;
@end

First and foremost, my answer is based on the latest Clang compiler, older versions worked slightly different. 首先,我的答案是基于最新的Clang编译器,旧版本的工作略有不同。

So, you're not creating an object in neither. 因此,您都不会同时创建对象。 You're not even declaring an object in two of them. 您甚至没有在两个对象中声明一个对象。

In the first case, you're actually telling the compiler that you need to expose a property called text of type NSString . 在第一种情况下,您实际上是在告诉编译器您需要公开一个称为NSString类型的text的属性。 What the compiler does, is declaring an instance variable for you _text (which you can access without a problem by the way) and the methods needed to get and set that instance variable. 编译器所做的就是为_text声明一个实例变量(您可以顺便访问它),以及获取和设置该实例变量所需的方法。 As you can see the storage is still internal, you just have getters and setters set for you. 如您所见,存储仍然是内部的,您只需要为自己设置getter和setter即可。

In the second case you're actually declaring an instance variable (ivar) yourself, just as the compiler does with _text . 在第二种情况下,实际上是您自己声明了一个实例变量(ivar),就像编译器对_text所做的那样。 It's accustom to prefix it with _ . 习惯上以_为前缀。 The storage is still internal. 存储仍然是内部的。 On top of that, you can't access your ivar from outside, since it has no getter or setter and the implicit declaration is @private . 最重要的是,您无法从外部访问ivar,因为它没有getter或setter且隐式声明是@private

In the third case, you create an anonymous category (thus the empty parentheses) which adds a property to your class. 在第三种情况下,您将创建一个匿名类别(因此为空括号),该类别将一个属性添加到您的类中。 Storage for this is a little bit harder/longer to explain, if you are curious about it, you can search up the Apple docs, see what a category is and so on. 对此的存储有些困难/需要较长的时间来解释,如果您对此感到好奇,可以搜索Apple文档,查看类别是什么,等等。 You can only access your property from within your class in this case, which makes it somehow redundant (the getters and setters), you could have declared it as an ivar. 在这种情况下,您只能从类内部访问属性,这使得它在某种程度上是多余的(getter和setter),您可以将其声明为ivar。

You can also declare your ivars like this: 您还可以这样声明自己的ivars:

@interface GenericViewController : UIViewController{
    NSString * text;
}

@end



@implementation GenericViewController{
    NSString * text;
}

@end

Both of the above have local storage and private visibility (can't be accessed from outside). 以上两个均具有本地存储和私有可见性(无法从外部访问)。 The difference between the two is that instance variables declared in the implementation are implicitly hidden and the visibility cannot be changed with @public, @protected and @private. 两者之间的区别在于,在实现中声明的实例变量被隐式隐藏,并且可见性无法使用@ public,@ protected和@private进行更改。 If you use those directives you won't get compiler errors but are ignored. 如果使用这些指令,则不会出现编译器错误,但会被忽略。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM