【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 函数的增强版,向控制台输出信息

    优势:

    1. 输出 调试信息(时间 程序名 进程编号 线程编号)+ 应输出内容;
    2. 输出结束会自动换行
    3. NSLog( )不仅可以输出 C 语言中的数据类型,还可以输出 OC 新增的数据类型
    // 使用方式
    NSLog(@"Hello, World!");
    NSLog(@"f1 = %f", 12.12f); // 占位符同 C 语言
    

    注意:

    1. “ ” 前要加 @
    2. 若 “ ” 内的结尾添加 \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中的 @ 符号

    1. 将 C 字符串转换为 OC 字符串

    2. OC中大部分关键字都以 @ 开头

      @autoreleasepool / @public / ...

  • 注释:同 C 语言(单行 / 多行)

  • 函数的定义 & 调用:同 C 语言


04 对比 OC & C

4.1 OC 程序的编译、链接、 执行

  1. 在 .m 文件中书写符合 OC 语法规范的代码

  2. cc -c xxx.m 编译源代码,生成目标文件(预处理 - 检查语法 - 编译)

  3. cc xxx.o 链接

    如果程序中使用了某些框架中的函数 / 类,在链接时需要告诉编译器所使用的框架

    cc xxx.o -framework 框架名称

  4. 链接成功后生成 a.out 可执行文件,执行程序

各阶段后缀名对比:

源文件 目标文件 可执行文件
C .c .o .out
OC .m .o .out

4.2 OC 中的常用数据类型

  1. C 语言中所有数据类型(基本数据类型 / 构造类型 / 指针 / void 空 / typedef 自定义)

  2. BOOL 类型(YES / NO)--> 存储条件表达式结果:成立 - YES;不成立 - NO

    BOOL b1 = num1 > num2;
    BOOL b2 = YES;
    

    本质:typedef signed char BOOL; // 实际上,BOOL类型的变量是一个有符号的 char 变量

    YES - 1;NO - 0

  3. Boolean 类型(true / false)--> 存储条件表达式结果:成立 - true;不成立 - false

    本质:typedef unsigned char Boolean;

-----以下内容会在后面的笔记中详细展开来讲-----

  1. class 类型(类)

  2. id 类型 (万能指针)

  3. SEL (方法选择器)

  4. 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. 归纳共同行为 ---> 这类事物都能做什么

---> 举例:【空调】:1 - 空调;2 - 品牌 / 颜色 / 功率 / 大小 / ... ;3 - 可制冷

6.4 如何找到类

  • 名词提炼法
    分析整个业务流程,总结出现的名词,这些名词就是类

07 类的定义

---> 先有类还是先有对象?
现实中:先有具体存在,后有抽象概念
代码中:先有类,再根据类创建对象

  • 如何定义一个类
    1. 类的三要素(类名,属性/特征,行为/功能)
    2. 定义类的语法
// 类的定义包含两部分
// 【1】类的声明
@interface Person : NSObject // 类名为 Person
{
	// 在此处,将类的共有属性定义为成员变量 
  NSString *_name;
  int _age;
  float _height;
}
// 将类的功能 --> 方法 的声明写在大括号外,@end 之前
@end
  
// 【2】类的实现
@implementation Person
  // 将方法的实现写在此处
@end 

注意:

  1. 类必须有声明 + 实现
  2. 类的命名规范:类名首字母应大写
  3. NSObject 不可省
  4. 定义在大括号内的表示共同特征的变量可称为:属性 / 成员变量 / 实例变量 / 字段 ...
  5. 类的变量命名规范:变量名应以 _ 下划线开头
  6. 类不要写在函数里

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];
    }
    
posted @ 2022-03-01 15:12  Z/z  阅读(1077)  评论(0)    收藏  举报