【Objective-C】1 OC基本语法
第一节 OC 基本语法
01 Objective-C 概述
1.1 Objective-C
---> 又称 OC, Obj-C :面向对象的 C 语言
- 本质还是 C 语言
- 在 C 的基础上添加一小部分面向对象的语法,将 C 语言复杂的语法封装的更简单
- 完全兼容 C 语言
1.2 历史简述
- 20th 80s,Brad Cox 结合 C & Smalltalk 设计出 OC
- 1985,乔布斯创建 NeXT,NeXT 设计出 NextStep(一套基于 OC 的一套强大的界面工具包)
- 1995,NeXT 获得OC全部版权
- 1996,Apple 收购 NeXT,NextStep 更名为 Cocoa,广泛用于开发 Mac 平台
1.3 OC现状 & 未来
- “前途堪忧” ---> Swift 面世(快速,现代,安全,互动,全面优于OC)
- 暂时不会被取代 ---> 新旧交替
02 快速演示 OC 程序
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"Hello, World!");
}
return 0;
}
03 OC 基础语法
-
源文件后缀名:.m
m 表示 message,代表 OC 中的消息机制
-
main( ) 函数依旧是 OC 程序的入口 & 出口
-
#import 指令:一种预处理指令,是 #include 的增强版
实现效果:将文件内容在预编译时拷贝到指令的位置,并可保证同一个文件只会包含 1 次(底层来判断)
---> 相当于实现了 #include + 条件编译指令 的效果
-
框架
---> 一个功能集,将开发时常用到的功能事先封装在一个个类 / 函数 中,这些函数 & 类的集合叫做框架(类似于C语言的函数库)
-
Foundation 框架:提供了最基础的功能(输入输出 / 数据类型 / 。。)
#import <Foundation/Foundation.h> // Foundation.h 这个文件中包含了 Foundation 框架中其他所有的头文件 // --> 只要包含了 Foundation.h,就相当于包含了整个 Foundation 框架 // --> 由此,Foundation 框架下的所有函数 & 类 都可以直接使用
-
-
@autoreleasepool :自动释放池
可以将代码写在自动释放池中,或者将自动释放删去直接写代码也可以
-
NSLog( ):printf 函数的增强版,向控制台输出信息
优势:
- 输出 调试信息(时间 程序名 进程编号 线程编号)+ 应输出内容;
- 输出结束会自动换行
- NSLog( )不仅可以输出 C 语言中的数据类型,还可以输出 OC 新增的数据类型
// 使用方式 NSLog(@"Hello, World!"); NSLog(@"f1 = %f", 12.12f); // 占位符同 C 语言
注意:
- “ ” 前要加 @
- 若 “ ” 内的结尾添加 \n ,自动换行失效(\n 出现在输出内容中间不会影响自动换行)
-
字符串
---> C:字符数组 / 字符指针
NSString 类型的指针变量:存储 OC 字符串的地址
注意:OC 的字符串常量必须要使用前缀 @
NSString *str = @"jack"; // 使用 str 来存储 oc 字符串 “jack” 的地址 // 非法语句: // NSString *str = "jack"; // 由于 "jack" 前面没有 @,所以为 C 字符串,不能被 NSString 类型存储
回顾 NSLog( ) 的输出形式:
NSLog(@"num = %d", num); // NSLog 函数的第一个参数是一个 OC 字符串(@" ") // 由此可知: // 【1】想要输出一个 OC 字符串,可写为: NSString *str = @"jack"; NSLog(str); // 输出内容为 jack // 【2】OC字符串的占位符为 %@,此时使用 %s 无效 NSLog(@"My name is %@.", str); // 输出 My name is jack.
-
NS前缀 ---> NextStep(Cocoa 前身)
-
OC中的 @ 符号
-
将 C 字符串转换为 OC 字符串
-
OC中大部分关键字都以 @ 开头
@autoreleasepool / @public / ...
-
-
注释:同 C 语言(单行 / 多行)
-
函数的定义 & 调用:同 C 语言
04 对比 OC & C
4.1 OC 程序的编译、链接、 执行
-
在 .m 文件中书写符合 OC 语法规范的代码
-
cc -c xxx.m 编译源代码,生成目标文件(预处理 - 检查语法 - 编译)
-
cc xxx.o 链接
如果程序中使用了某些框架中的函数 / 类,在链接时需要告诉编译器所使用的框架
cc xxx.o -framework 框架名称
-
链接成功后生成 a.out 可执行文件,执行程序
各阶段后缀名对比:
源文件 | 目标文件 | 可执行文件 | |
---|---|---|---|
C | .c | .o | .out |
OC | .m | .o | .out |
4.2 OC 中的常用数据类型
-
C 语言中所有数据类型(基本数据类型 / 构造类型 / 指针 / void 空 / typedef 自定义)
-
BOOL 类型(YES / NO)--> 存储条件表达式结果:成立 - YES;不成立 - NO
BOOL b1 = num1 > num2; BOOL b2 = YES;
本质:typedef signed char BOOL; // 实际上,BOOL类型的变量是一个有符号的 char 变量
YES - 1;NO - 0
-
Boolean 类型(true / false)--> 存储条件表达式结果:成立 - true;不成立 - false
本质:typedef unsigned char Boolean;
-----以下内容会在后面的笔记中详细展开来讲-----
-
class 类型(类)
-
id 类型 (万能指针)
-
SEL (方法选择器)
-
block(代码段)
4.3 运算符 / 控制语句
C 语言中使用的运算符 / 控制语句全部可用于 OC
4.4 关键字
-
OC 支持 C 语言中所有关键字,且效果一致
-
OC 新增了一些关键字,绝大多数以 @ 开头
@interface / @implementation / @public / ...
4.5 函数的定义与调用
OC 中函数的定义与调用 和 C 语言完全一致
- 总结:OC 语言完全兼容 C 语言
05 面向过程与面向对象
面向过程与面向对象是解决问题的两种思路。
- 面向过程:独自解决问题的每一个步骤,亲自写出所有步骤的代码
- 面向对象:寻找是否已存在某些功能可以实现需求。有则直接调用;没有则创建一个能够实现需求,且可以重复使用的功能
面向对象的优点:方便后期的维护和修改
06 类与对象
6.1 概念
- 类:对一群拥有相同特征 / 行为的具体事物的统称 ---> 抽象,不能直接使用
- 对象:一个具体存在,可直接对其操作
---> 举例:
类 | 对象 |
---|---|
食物,水果,苹果,红苹果 | 桌子上的那一个苹果 |
交通工具,车,汽车,奔驰汽车 | 车牌号为 bf431 的奔驰汽车 |
6.2 类与对象的关系
类是模板,类的对象是根据这个模板创建出来的。类模板中有什么,对象中就包含什么,不多也不少。
类是抽象的,不可使用。如果要使用类,必须通过一个具体存在的对象来实现。
6.3 如何设计一个类
- 指定类的名字
- 归纳共同特征 ---> 这类事物都有什么属性
- 归纳共同行为 ---> 这类事物都能做什么
---> 举例:【空调】:1 - 空调;2 - 品牌 / 颜色 / 功率 / 大小 / ... ;3 - 可制冷
6.4 如何找到类
- 名词提炼法
分析整个业务流程,总结出现的名词,这些名词就是类
07 类的定义
---> 先有类还是先有对象?
现实中:先有具体存在,后有抽象概念
代码中:先有类,再根据类创建对象
- 如何定义一个类
- 类的三要素(类名,属性/特征,行为/功能)
- 定义类的语法
// 类的定义包含两部分
// 【1】类的声明
@interface Person : NSObject // 类名为 Person
{
// 在此处,将类的共有属性定义为成员变量
NSString *_name;
int _age;
float _height;
}
// 将类的功能 --> 方法 的声明写在大括号外,@end 之前
@end
// 【2】类的实现
@implementation Person
// 将方法的实现写在此处
@end
注意:
- 类必须有声明 + 实现
- 类的命名规范:类名首字母应大写
- NSObject 不可省
- 定义在大括号内的表示共同特征的变量可称为:属性 / 成员变量 / 实例变量 / 字段 ...
- 类的变量命名规范:变量名应以 _ 下划线开头
- 类不要写在函数里
08 对象
- 类是无法直接使用的,只能对类的对象进行操作
8.1 如何创建某个类的对象
@interface Person : NSObject
{
NSString *_name;
int _age;
float _height;
}
@end
@implementation Person
@end
int main(){
Person *p1 = [Person new]; // 根据 Person 类这个模版,创建了一个对象 p1
}
8.2 如何使用对象
// 默认情况下,对象的属性是允许被外界访问的
// 如果要允许对象的属性可以被外界访问,需要在声明属性时添加 @public 关键字
// 访问对象的属性有两种方式
// 【1】p1->_name = @"jack";
// 将 jack 这个oc字符串存入 p1 的 _name 这个属性中
// 【2】(*p1)._age = 18;
// 建议使用 -> 【1】
09 方法的声明、实现与调用
@interface Person : NSObject
{
NSString *_name;
int _age;
float _height;
}
// 方法的声明
- (void)run; // 声明了一个无返回值且无参数的方法
- (void)eat:(NSString*)foodName; // 声明一个无返回值但有参数的方法,方法名称为【 eat: 】
- (int)sum:(int)num1 :(int)num2; // 声明返回 int,有两个参数的方法。参数之间用【空格 + :】隔开
@end
@implementation Person
// 方法的实现:将其声明复制粘贴到此处,删去分号,添加大括号
- (void)run{
NSLog(@"running");
}
- (void)eat:(NSString*)foodName{
NSLog(@"eatting %@", foodName);
}
- (int)sum:(int)num1 :(int)num2{
return num1 + num2;
}
@end
int main(){
Person *p1 = [Person new];
// 方法的调用(类的方法只能通过具体对象调用)
[p1 run];
[p1 eat:@"apple"];
int num = [p1 sum:1 :2];
}
-
带一个参数的方法命名规范:在方法名尾部添加后缀 With / Withxxx(参数的特征)
@interface Person : NSObject - (void)eatWith:(NSString*)foodname; @end @implementation - (void)eatWith:(NSString*)foodname{ NSLog(@"eatting %@", foodname); } @end int main(){ Person *p = [Person new]; [p eatWith:@"apple"]; // 可读性更高,写成 eatWithFood 也很好 }
-
多个参数的方法命名规范:
@interface Person : NSObject - (int)sumWith:(int)num1 and:(int)num2 and:(int)num3; // 添加了 With & and // 该方法名字为 sumWith: and: and: @end @implementation - (int)sumWith:(int)num1 and:(int)num2 and:(int)num3{ return num1 + num2 + num3; } @end int main(){ Person *p = [Person new]; int num = [p sumWith:1 and:2 and:3]; // 将方法命名成 sumWithNum1: andNum2: andNum3 也很好 // 则调用语句变为: // int num = [p sumWithNum1:1 andNum2:2 andNum3:3]; // 可读性更高 }
10 其他注意
-
同一个类可以创建多个对象,但对象之间毫无关系,不会相互影响
-
在方法的实现中可以访问类的属性,调用时才会实际访问,访问的是调用该方法的对象的属性
// 案例:定义一个 Person 类 // 属性:name, weight // 功能: // 1 跑步 :weight -0.5; 2 吃饭:weight + 0.7 @interface Person : NSObject{ NSString* _name; float _weight; } - (void)run; - (void)eat; @end @implementation Person - (void)run{ _weight -= 0.5; NSLog(@"%@'s weight is %f", _name, _weight); } - (void)eat{ _weight += 0.7; NSLog(@"%@'s weight is %f", _name, _weight); } @end int main(){ Person *jack = [Person new]; jack->_name = @"jack"; jack->_weight = 66.6f; [jack run]; [jack eat]; }