Objective-C的语法之OOP
关于OC类定义中的变量声明和使用说明:
- 实例变量
- 全局变量
- 实例方法
- *类方法
拆分接口和实现
一般OC类的定义分为两部分:一部分是接口.h文件(@interface),用来展示类的构造,包含了使用该类所需的所有信息;另一部分是实现.m文件(@implement),这部分代码实现了接口中声明的所有方法。
.h文件中一般会包括:@interface指令、公共struct定义、enum常量、extern全局变量、#define、@property属性声明和方法声明(实例方法和类方法)等。
.m文件一般包含:@implement指令、全局变量的定义、私有struct和方法实现等。
目录
用 [TOC]
来生成目录:
接口文件
.h接口文件,一般的内容格式如下:
#import <Foundation/Foundation.h>
@interface Car : NSObject //继承NSObject类
//大括号用来声明类的实例变量(如果没有,则可以省略大括号)
{
int _speed;
}
//使用@property指令声明属性(public)
@property (nonatomic, strong) NSString *color;
@property (nonatomic, assign) int weight;
//声明实例方法
- (void)setSpeed:(int)speed;
- (int)speed;
@end
OC中区分函数原型与方法声明的方式:函数原型中没有先行短横线(方法声明才会有短横线)。
分析以下语句:
- (void)setSpeed:(int)speed;
其中冒号“:”表示方法后面会出现参数,如果方法不含参数则不需要冒号,如“-(int) speed;”一样。
(int)表示参数类型,参数的类型在圆括号中指定;speed 是参数名(注意参数名不要和属性名相同)。
实现文件
.m实现文件,一般的内容格式如下:
#import "Car.h"
NSString *manufacture_date; //全局变量
@implementation Car
NSString *manufacturer; //全局变量
{
NSString *owner; //类的私有变量(只能在.m文件中访问)
}
/* 在Xcode4.5之后,使用@property关键字时,Xcode会自动生成 @synthesize 语句(在.m文件中可以省略@synthesize,实例变量的名称为“_属性名”)*/
//@synthesize color = _color;
//表示使用_color(下划线属性名)作为实例变量,存储color属性
- (void)setSpeed:(int)speed
{
_speed = speed;
}
- (int)speed
{
return _speed;
}
-(void)dealloc
{
//访问速度属性的方法:
//直接访问属性 _speed self->_speed
//通过get方法间接访问 [self speed] self.speed
NSLog(@"颜色为%@的Car对象被回收了!", self->_color); //self->_color 访问实例变量_color
NSLog(@"颜色为%@的Car对象被回收了!", _color); //在类内部直接使用实例变量_color
NSLog(@"颜色为%@的Car对象被回收了!", self.color); //self.color 通过getter方法来访问实例变量_color
NSLog(@"颜色为%@的Car对象被回收了!", [self color]); //[self color] 通过getter方法来访问实例变量_color
NSLog(@"重量为%d的Car对象被回收了!", self->_weight);
NSLog(@"速度为%d的Car对象被回收了!", self.speed);
NSLog(@"速度为%d的Car对象被回收了!", [self speed]);
[super dealloc];
}
@end
类实现部分(在@implement中)也可以声明自己的成员变量,但这些成员变量只能在当前类内访问(相当于隐藏的成员变量),比如上面代码中的owner,私有的成员变量定义在 { } 中。
对于以上.m文件中的manufacturer变量,实际上该变量为全局变量,所有Car对象的实例共享同一个manufacturer全局变量,但是通常我们会将全局变量的定义放在@implement之前(就像定义manufacture_date全局变量一样),可以参考这个回答
关于方法的定义,其中冒号“:”表示方法后面会出现参数,如果方法不含参数则不需要冒号,如“-(int) speed;”一样。
(int)表示参数类型,参数的类型在圆括号中指定;speed 是参数名(注意参数名不要和属性名相同)。
注意,使用@property时有时会出现以下警告:(例如,animator是声明的属性名)
Auto property synthesis will not synthesize property ‘animator’; it will be implemented by its superclass, use @dynamic to acknowledge intention。
原因是:父类中有一个同名的属性,此时我们可以使用@dynamic指令(在@implement中),告知编译器这个属性是动态的,“动态”的意思是等你编译的时候就知道了它只在本类合成。
另外,点符号只用于属性,表示方法调用,使用“.”来调用属性的setter和getter方法(不要用于其它方法)。
总结
OC将类分成接口(interface)部分和实现(implementation)部分,接口部分定义的成员变量和方法是对外暴露的(可以被外界调用),实现部分定义的内容对外部是隐藏的,只能在内部调用。