声明/定义ObjectiveC中变量位置的方法? In ObjectiveC, variables can be declared/defined in several locations within a program. These locations include: 1. Within a method or function: Variables can be declared/defined within the body of a method or function. These va
声明/定义ObjectiveC中变量位置的方法? In ObjectiveC, variables can be declared/defined in several locations within a program. These locations include: 1. Within a method or function: Variables can be declared/defined within the body of a method or function. These va
自从开始开发iOS应用和Objective C以来,我一直对声明和定义变量的不同位置感到困惑。一方面,我们有传统的C方法,另一方面,我们有在其之上添加了面向对象特性的新的ObjectiveC指令。您能帮我理解最佳实践和在何种情况下我应该使用这些位置来声明变量,并纠正我目前的理解吗?
这是一个示例类(.h和.m):
#import// 1) 我应该在这里声明什么? @interface SampleClass : NSObject { // 2) 实例变量的声明 // 很少使用? } // 3) 类特定的方法/属性声明 @end
#import "SampleClass.h" // 4) 这里应该写什么? @interface SampleClass() // 5) 私有接口,可以在这里定义私有方法和属性 @end @implementation SampleClass { // 6) 定义实例变量 } // 7) 定义方法并从公共和私有接口合成属性 @end
- 对于1和4,我的理解是它们是基于文件的C风格声明和定义,完全不理解类的概念,因此必须像在C中一样使用它们。我以前看到它们被用于实现基于静态变量的单例模式。是否还有其他方便的用途我忽略了?
- 在使用iOS时,我发现实例变量在除了@synthesize指令之外几乎不再使用,因此可以基本忽略它们。是否是这样?
- 关于5:为什么我要在私有接口中声明方法?我的私有类方法似乎在没有在接口中声明的情况下也可以编译通过。这主要是为了可读性吗?
非常感谢!
Objective-C中变量的声明和定义位置的问题是由于新手对语言不熟悉而引起的。解决这个问题的方法是了解不同位置的变量声明和定义的作用和范围。
在Objective-C中,变量的声明和定义可以出现在以下位置:
1. C风格的全局变量:它们具有文件范围的作用域。第一个全局变量可以在导入头文件的任何地方使用,而第二个则不能。
2. 实例变量:大多数实例变量是通过属性的访问器进行合成和获取/设置的,这样可以使内存管理变得简单,并且可以使用易于理解的点表示法。
3. 公共方法和属性的声明和实现。
4. 实现中的实例变量:这个位置是相对较新的,适合放置私有实例变量,因为您只想在公共头文件中暴露所需的内容,而子类不会继承它们。
5. 私有接口:如果其他部分不需要知道它,可以将其放在这里。我还这样做是为了提高可读性。
此外,现在不再需要提前声明私有方法。
以上是Objective-C中变量的声明和定义位置的概述。通过了解每个位置的作用和范围,可以更好地组织代码并提高可读性。在实际编码中,可以根据需要选择合适的位置来声明和定义变量。
Objective-C中变量的声明和定义存在多种位置,下面是对各个位置的解释:
1. 在#import
2. 在类的声明中,即@interface之后和大括号之前,不应该放任何内容。这是一种遗留的写法,不应使用。
3. 在类的声明之后,可以声明类特定的方法和属性。
4. 在#import "SampleClass.h"之后,可以放置外部常量和文件静态变量。文件静态变量相当于其他语言中的类变量。
5. 在SampleClass()中可以定义私有接口,在这里可以定义私有方法和属性。
6. 在SampleClass中定义实例变量的方式很少见,通常应该让Xcode自动生成变量。只有在非Objective-C实例变量(如Core Foundation对象,特别是如果这是一个Objective-C++类)或具有奇怪存储语义的实例变量(如与属性不匹配的实例变量)时,才需要手动定义。
7. 在类的实现中可以定义方法和生成来自公共和私有接口的属性。
不久前,Objective-C的情况变得简单得多。然而,由于不同时期的代码存在差异,因此可能会导致一些混淆。因此,简单性带来了混淆。
关于为什么不应该显式synthesize,原因在于它并没有真正提供任何有用的文档信息。即使使用了synthesize,你可能已经重写了一个或两个访问器,从synthesize的一行代码中无法得到任何有用的信息。错误的文档比没有文档更糟糕,所以最好不要使用。
为什么#6很少使用?因为获取私有属性的最简单和最好的方式是使用#5。
需要注意的是,有时仍然需要使用@synthesize,例如当一个属性是只读的并且它的访问器被重写时。
Objective-C中变量的声明和定义位置是一个常见的问题。特别是最近Xcode的更新和新的LLVM编译器改变了ivars和properties的声明方式。
在“旧”的Objective-C 2.0中,你只有很少的选择。实例变量被声明在头文件的花括号之间:
// MyClass.h MyClass : NSObject { int myVar; }
你只能在实现文件中访问这些变量,而不能从其他类中访问。为了实现从其他类访问,你需要声明访问器方法,如下所示:
// MyClass.h MyClass : NSObject { int myVar; } - (int)myVar; - (void)setMyVar:(int)newVar; // MyClass.m MyClass - (int)myVar { return myVar; } - (void)setMyVar:(int)newVar { if (newVar != myVar) { myVar = newVar; } }
这样,你就可以使用常规的方括号语法发送消息(调用方法)从其他类获取和设置这个实例变量:
// OtherClass.m int v = [myClass myVar]; // 假设myClass是一个MyClass类型的对象 [myClass setMyVar:v+1];
因为手动声明和实现每个访问器方法非常繁琐,所以引入了`@property`和`@synthesize`来自动生成访问器方法:
// MyClass.h MyClass : NSObject { int myVar; } @property (nonatomic) int myVar; // MyClass.m MyClass @synthesize myVar;
这样可以得到更清晰和更短的代码。访问器方法将会自动生成,你仍然可以像以前一样使用方括号语法。此外,你还可以使用点语法来访问属性:
// OtherClass.m int v = myClass.myVar; // 假设myClass是一个MyClass类型的对象 myClass.myVar = v+1;
从Xcode 4.4开始,你不再需要自己声明实例变量,也可以省略`@synthesize`。如果你不声明实例变量,编译器会自动为你添加,并且也会自动生成访问器方法,无需使用`@synthesize`。
自动生成的实例变量的默认名称是以下划线开头的属性名称。你可以使用`myVar = iVarName;`来更改自动生成的实例变量的名称:
// MyClass.h MyClass : NSObject @property (nonatomic) int myVar; // MyClass.m MyClass
这段代码与上面的代码完全相同。出于兼容性的原因,你仍然可以在头文件中声明实例变量。但是因为你这样做的唯一原因(而不是声明一个属性)是创建一个私有变量,所以现在你也可以在实现文件中这样做,这是首选的方法。
在实现文件中的`@implementation`块实际上是一个扩展,可以用于前向声明方法(不再需要),以及(重新)声明属性。例如,你可以在头文件中声明一个`readonly`属性:
@property (nonatomic, readonly) myReadOnlyVar;
然后在实现文件中重新声明它为`readwrite`,以便可以使用属性语法进行设置,而不仅仅通过直接访问实例变量。
至于在任何`@interface`或`@implementation`块之外声明变量,是普通的C变量,使用方式完全相同。
总之,Objective-C中变量的声明和定义位置有一些变化,但是通过使用属性和自动生成的访问器方法,可以更清晰和更简洁地编写代码。