Objective-C面向对象编程:类、对象、方法详解(保姆级教程)
目录
一、核心概念
二、类的定义(分.h和.m文件)
1. 头文件(.h)—— 公开声明
2. 实现文件(.m)—— 具体实现
3. 属性特性解析
原子性
所有权语义(ARC环境下)
读写控制
三、对象创建与内存管理
1. 创建对象的两种方式
2. 关键步骤解析
3. instancetype
四、方法调用(消息传递机制)
1. 基本语法
2. 关键概念
五、self与super关键字
六、动手实践:完整工作流
1. 创建Person对象并调用方法
2. 项目结构
七、关键概念对比表
八、常见问题解答
相关推荐
一、核心概念
- 类:对象的蓝图(定义属性和方法)
- 对象:类的实例(内存中的具体实体)
- 方法:对象的行为(实例方法
-
/ 类方法+
)
二、类的定义(分.h和.m文件)
1. 头文件(.h)—— 公开声明
#import <Foundation/Foundation.h>@interface SccUser : NSObject // 继承NSObject// 属性声明(编译器自动生成getter/setter)
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSInteger age;// 方法声明
- (void)sayHello; // 实例方法
+ (void)run; // 类方法@end
编译器的自动合成:
- 自动生成实例变量(默认带下划线前缀:
_name
,_age
) - 自动生成getter和setter方法
- 根据属性特性自动处理内存管理
2. 实现文件(.m)—— 具体实现
#import "SccUser.h"@implementation SccUser- (void)sayHello {NSLog(@"say:HelloKitty");
}+ (void)run {NSLog(@"奔跑吧,类方法。");
}@end
3. 属性特性解析
属性特性分为三类:原子性、所有权语义和读写控制。
原子性
atomic
(默认):线程安全的getter/setter,但性能稍低nonatomic
:非线程安全,但性能更好(推荐在单线程环境使用)
所有权语义(ARC环境下)
特性 | 适用类型 | 描述 |
---|---|---|
strong | 对象类型 | 默认值,保持强引用,引用计数+1 |
weak | 对象类型 | 弱引用,不增加引用计数,对象释放后自动置nil(解决循环引用) |
assign | 基本数据类型 | 简单赋值,不进行引用计数管理(用于int, float, BOOL等) |
copy | 对象类型(特别是NSString/NSArray等) | 创建对象的副本(保护不可变对象不被外部修改) |
unsafe_unretained | 对象类型 | 类似assign,但对象释放后不自动置nil(不安全,尽量用weak代替) |
读写控制
readwrite
(默认):生成getter和setterreadonly
:只生成getter
三、对象创建与内存管理
1. 创建对象的两种方式
// 标准方式(推荐)
SccUser *user1 = [[SccUser alloc] init]; // 简化方式(等效于alloc+init)
SccUser *user2 = [SccUser new];
2. 关键步骤解析
方法 | 作用 |
---|---|
alloc | 分配内存(从堆区申请空间) |
init | 初始化对象(设置默认值) |
✅ 最佳实践:自定义初始化方法示例
// SccUser.h中添加
- (instancetype)initWithName:(NSString *)name;// SccUser.m中实现
- (instancetype)initWithName:(NSString *)name {self = [super init];if (self) {_name = name; // 直接访问底层实例变量}return self;
}
3. instancetype
instancetype
是 Objective-C 引入的编译时类型检查关键字,用于表示:
"这个方法返回的实例类型,就是当前类的类型"
与 id
的对比(核心区别)
特性 | instancetype | id (通用对象指针) |
---|---|---|
类型安全性 | ✅ 编译器会检查类型一致性 | ❌ 绕过类型检查 |
代码智能提示 | ✅ Xcode 提供精确的代码补全 | ❌ 只能提示通用方法 |
继承场景行为 | ✅ 子类继承时自动匹配实际类型 | ❌ 永远返回 id |
编译时优化 | ✅ 编译器可进行静态分析 | ❌ 无优化 |
四、方法调用(消息传递机制)
1. 基本语法
SccUser *user = [SccUser new];
// 无参数方法
[user sayHello];// 类方法
[SccUser run];// 带参数方法(冒号是语法关键)
[user setName:@"ShuaiciMain"]; // 等效于user.name = @"ShuaiciMain";// 多参数方法
[user userInfo:@"DaShuaiCi" is:18];
2. 关键概念
- 选择器(SEL):
@selector(sayHello)
表示方法签名 - 消息传递:
[receiver message]
被编译为objc_msgSend(receiver, selector)
五、self与super关键字
关键字 | 作用 | 示例 |
---|---|---|
self | 当前对象(类似Java/C++的this ) | self.name = @"Bob"; |
super | 调用父类实现 | [super init]; |
⚠️ 易错点:在
init
方法中必须用_name
访问属性,避免触发未初始化的KVO
六、动手实践:完整工作流
1. 创建Person对象并调用方法
#import <Foundation/Foundation.h>
#import "SccUser.h"int main(int argc, const char * argv[]) {@autoreleasepool {// 1. 创建对象SccUser *alice = [[SccUser alloc] init];// 2. 设置属性(点语法本质是调用setter)alice.name = @"ShuaiciMain";// 3. 调用实例方法[alice sayHello];[alice userInfo:@"DaShuaiCi" is:18];// 4. 调用类方法[SccUser run];// 5. 使用自定义初始化SccUser *shuaici = [[SccUser alloc] initWithName:@"DaShuaiCi"];NSLog(@"自定义初始化:%@",shuaici.name);}return 0;
}
2. 项目结构
YourProject/
├── Person.h // 头文件(声明)
├── Person.m // 实现文件
└── main.m // 程序入口
七、关键概念对比表
特性 | 实例方法 | 类方法 |
---|---|---|
语法符号 | - (减号) | + (加号) |
调用对象 | 类的实例 | 类本身(如[Person ...] ) |
内存归属 | 对象内存空间 | 类元数据空间 |
访问权限 | 可访问实例变量 | 不可访问实例变量 |
典型用途 | 对象的具体操作 | 工厂方法/工具类方法 |
八、常见问题解答
Q1:为什么属性用copy
修饰字符串?
防止NSMutableString被意外修改(
copy
会创建不可变副本)
Q2:alloc
和init
能分开调用吗?
可以但不推荐(可能产生未初始化对象):
Person *p = [Person alloc]; // 只有内存分配 p = [p init]; // 完成初始化
Q3:方法命名规范?
苹果官方要求:
- 参数名嵌入方法名(
sendData:toAddress:withTimeout:
)- 驼峰命名法(首个单词小写)
Q4:如何理解消息传递?
Objective-C运行时动态绑定过程:
- 通过
isa
指针查找对象类- 在类的方法列表中查找SEL
- 若未找到则向父类传递消息
- 最终未处理则触发
unrecognized selector
异常
相关推荐
为何要学习Objective-C?从环境搭建开始-CSDN博客文章浏览阅读514次,点赞10次,收藏10次。在Objective-C开发中,你会频繁遇到以"NS"开头的类名和函数名,比如NSLog、NSString、NSArray等。这个"NS"前缀其实有着重要的历史渊源和技术含义。https://shuaici.blog.csdn.net/article/details/148535298C语言基础精讲-CSDN博客文章浏览阅读10w+次,点赞413次,收藏2.1k次。C语言是当代人学习及生活中的必备基础知识,应用十分广泛,下面为大家带来C语言基础知识梳理总结,C语言零基础入门绝对不是天方夜谭!_c语言基础知识
https://shuaici.blog.csdn.net/article/details/60570837