作为初学者,理解类与对象是掌握 Objective-C 的第一步。我会用"汽车工厂"的比喻贯穿始终,帮你建立直观认识。
一、核心概念:类 vs 对象
1. 类 (Class) - 蓝图/模板
类是对象的定义说明书,描述对象有什么(属性)和能做什么(方法)。
类比:汽车设计图纸,定义了"汽车应该有四个轮子、一个引擎,可以加速和刹车"。
2. 对象 (Object) - 实例
对象是类的具体个体,根据类创建出来的真实存在。
类比 :根据图纸制造出的每一辆具体的汽车(你的宝马、我的特斯拉)。
二、定义一个类(以 Car 为例)
Objective-C 中,每个类由两个文件组成:
1. 接口文件 (Car.h) - 对外声明
objc
// Car.h
#import
@interface Car : NSObject // 继承自 NSObject
{
// 实例变量(现在很少直接写这里)
int _wheels; // 轮子数量
NSString *_brand; // 品牌
}
// 属性(推荐方式)
@property (nonatomic, strong) NSString *color; // 颜色
@property (nonatomic, assign) int maxSpeed; // 最高时速
// 方法声明
- (void)drive; // 驾驶(实例方法)
- (void)stop; // 停止(实例方法)
+ (void)horn; // 鸣笛(类方法)
@end
关键字解析:
| 关键字 | 含义 | 说明 |
|---|---|---|
@interface |
接口开始 | 声明类的公共接口 |
@end |
接口结束 | 必须有 |
: NSObject |
继承 | 所有类最终都继承自 NSObject |
@property |
属性 | 自动生成 getter/setter 方法 |
nonatomic |
非原子性 | 性能更好,不考虑多线程 |
strong |
强引用 | ARC 下持有对象(防止被释放) |
assign |
赋值 | 用于基本类型(int/float 等) |
2. 实现文件 (Car.m) - 内部实现
objc
// Car.m
#import "Car.h"
@implementation Car
// 实现初始化方法(构造器)
- (instancetype)init {
self = [super init];
if (self) {
_wheels = 4; // 默认4个轮子
_brand = @"Unknown";
self.color = @"Black";
self.maxSpeed = 120;
}
return self;
}
// 实例方法实现
- (void)drive {
NSLog(@"%@ 汽车正在行驶,最高时速 %d km/h", _brand, self.maxSpeed);
}
- (void)stop {
NSLog(@"%@ 汽车已停止", _brand);
}
// 类方法实现
+ (void)horn {
NSLog(@"滴滴滴!这是类方法,不需要具体汽车就能调用");
}
@end
为什么分 .h 和 .m?
- .h:对外暴露的"使用说明书",其他类通过它知道如何调用你
- .m:内部实现的"商业机密",隐藏具体实现细节
三、创建和使用对象
在 main.m 中测试
objc
#import
#import "AppDelegate.h"
#import "Car.h"
int main(int argc, char * argv[]) {
@autoreleasepool {
// 1. 创建对象(实例化)
Car *myCar = [[Car alloc] init];
// 2. 使用点语法设置属性
myCar.color = @"Red";
myCar.maxSpeed = 180;
// 3. 调用方法(消息传递)
[myCar drive]; // 输出: Unknown 汽车正在行驶,最高时速 180 km/h
// 4. 创建另一辆车
Car *yourCar = [[Car alloc] init];
yourCar.color = @"Blue";
[yourCar drive]; // 这是另一辆独立的车
// 5. 调用类方法
[Car horn]; // 输出: 滴滴滴!这是类方法,不需要具体汽车就能调用
appDelegateClassName = NSStringFromClass([AppDelegate class]);
}
return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}
创建对象的两步语法
objc
Car *myCar = [[Car alloc] init];
// ↑ ↑ ↑ ↑
// 1 2 3 4
// 1: Car *myCar - 声明一个指向 Car 对象的指针
// 2: [Car alloc] - 向 Car 类发送消息:分配内存空间
// 3: init - 调用初始化方法(构造函数)
// 4: = - 将内存地址赋值给指针
更简洁的写法:
objc
Car *myCar = [Car new]; // 等同于 [[Car alloc] init]
四、方法类型对比
实例方法 (Instance Method)
objc
- (void)drive; // 以 - 开头
- 调用方式 :
[对象 方法],如[myCar drive] - 特点 :可以访问具体对象的属性(如
_brand、self.color)
类方法 (Class Method)
objc
+ (void)horn; // 以 + 开头
- 调用方式 :
[类名 方法],如[Car horn] - 特点:不依赖具体对象,常用于工具类、工厂方法
五、属性 vs 实例变量
现代开发方式(用 @property)
objc
// 在 .h 中
@property (nonatomic, strong) NSString *color;
编译器会自动生成:
objc
// 生成的实例变量(自动加下划线)
NSString *_color;
// 生成的 getter 方法
- (NSString *)color {
return _color;
}
// 生成的 setter 方法
- (void)setColor:(NSString *)color {
_color = color;
}
使用方式
objc
// 三种写法等价,推荐第一种
myCar.color = @"Red"; // 点语法(推荐)
[myCar setColor:@"Red"]; // 消息语法
[myCar setColor:@"Red"]; // 直接调用 setter
六、继承 (Inheritance)
objc
// ElectricCar.h
#import "Car.h" // 导入父类
@interface ElectricCar : Car // 继承自 Car
@property (nonatomic, assign) int batteryLevel; // 新增属性
- (void)charge; // 新增方法
@end
// ElectricCar.m
@implementation ElectricCar
- (instancetype)init {
self = [super init]; // 先调用父类初始化
if (self) {
self.maxSpeed = 200; // 修改继承来的属性
self.batteryLevel = 100;
}
return self;
}
- (void)charge {
NSLog(@"%@ 正在充电...", self.color);
}
// 重写父类方法
- (void)drive {
[super drive]; // 调用父类实现
NSLog(@"(无声电动车)");
}
@end
使用:
objc
ElectricCar *tesla = [[ElectricCar alloc] init];
tesla.color = @"White";
[tesla drive]; // 调用重写后的方法
[tesla charge]; // 调用子类新方法
七、内存管理基础(ARC)
关键概念
- ARC (Automatic Reference Counting):自动引用计数,编译器自动管理内存
- 强引用 (strong):持有对象,"只要我还用,它就不能释放"
- 弱引用 (weak):不持有对象,"我用它,但它可以被释放,释放后自动变 nil"
常见场景
objc
@property (nonatomic, strong) NSArray *data; // 持有数据
@property (nonatomic, weak) id delegate; // 代理通常为 weak,防止循环引用
@property (nonatomic, weak) IBOutlet UIButton *button; // UI 元素用 weak
八、总结与最佳实践
| 规则 | 说明 |
|---|---|
| 文件命名 | 类名与文件名保持一致(如 Car.h/Car.m) |
| 属性优先 | 99% 情况用 @property,不用手写实例变量 |
| 初始化 | 自定义类必须重写 init 方法 |
| 方法命名 | 用动词开头,清晰表达功能(如 drive、stop) |
| 内存管理 | 默认用 strong, delegate 和 IBOutlet 用 weak |
| 继承 | 避免过深的继承层次,iOS 推荐用组合代替继承 |
初学者必须记住的3句话
- 类是模板,对象是实例 - 先有图纸,后有汽车
- [] 是 Objective-C 的灵魂 - 所有方法调用都用中括号
- alloc/init 是对象的生命起点 - 记住这个组合
九、练习题
尝试创建一个 Student 类:
- 属性:姓名(name)、年龄(age)、学号(studentID)
- 方法:学习(study)、睡觉(sleep)
- 在 main.m 中创建两个学生对象并调用方法