OC基础DAY03 - 封装

对象作为方法的参数
- (BOOL)isOlderWithOthetDog:(HMDog *)otherDog
{
    if(_age > otherDog->_age)
    return YES;
    return NO;
}

#define LOGBOOL(val) NSLog(@"%@",val == YES ? @"YES":@"NO")
LOGBOOL(res);
异常处理
  1. 错误
    1. 一般情况下指的是我们的程序员代码有语法错误.
    2. 错误的后果就是无法编译.更谈不上执行.
    3. 解决方案:将错误的代码修改为符合语法规范的代码就OK了.
    4. BUG

计算机还是很庞大的体积的时候,一只虫子使电路板断路造成停摆,找到以后就讲计算机的错误命名为BUG了
  1. 指的是,程序可以编译,链接,执行.只不过程序执行出来的记过并不是我们所预想的那样.
  2. 解决方案: 99%的Bug都是因为变量的值没有按照我们所预想的那样去变化.通过断点调试去监视变量的值是如何变化的,分析为什么会乱变化.
  3. 异常
  4. 概念:指的是程序可以编译,链接,执行.当程序在运行的时候,处在某种特殊情况下的时候,程序的执行就会报错.
  5. 特点:不是一定会发生,而是在处于某种特定情况下的时候才会发生.
  6. 后果:程序立即终止运行,后面的代码不会执行了.
  7. 异常的处理
  8. 处理的目的,希望程序发生异常不要崩溃,而是继续往下执行.
  9. 使用@try…@catch来处理异常
  10. 将有可能发生异常的代码使用@try围起来
    @try
    {
        在执行的时候有可能会发生异常的代码;
    }
    @catch(NSException *ex)
    {

    }
  1. 执行步骤
    a. 如果@try中的代码在执行的时候,发生了异常,这个时候程序不会崩溃,而是会立即跳转到@catch中执行代码.@catch中的代码执行完毕后,再继续往下执行
    b. 如果@try中的代码没有发生异常,就跳过@catch,继续往下执行,
  2. 作用:让我们程序在崩溃的时候,继续往下运行.
  3. 使用注意,如果发生了异常,会将发生异常的信息,封装为一个NSException对象.再把对象的地址赋给*ex,再执行@catch.
  4. 在@catch中如果想拿到发生异常的原因,就可以访问参数对向 方法是
NSString *re = [ex reason];
@catch中一般写处理异常的代码

后面还可以跟一个
@finally
{
    无论有没有发生异常,都执行finally中的代码
}
  1. try并不是万能的,不是所有的异常都可以处理. C语言的异常处理不了,OC的也不是全部都能处理.该崩还是崩.所以平时写代码很少用.
  2. 我们一般通过逻辑判断来处理异常

    if(num2 == 0)
    {
    NSLog(@”除数不能为0”);
    }
    else
    {
    int num3 = num1/num2;
    }

类方法的基本使用
类方法不用依赖于对象,通过类名就可以调用
  1. 声明
类方法使用+号声明,跟对象方法相反
+ (void)classMethod
{
    代码
}
  1. 调用不需要创建对象,直接使用类名

    [HMperson classMethod];

==类方法只能通过类名调用,不能通过对象名==
- 类方法的特点

  1. 节约空间,不需要创建对象.对象方法还要先创建一个对象.
  2. 提高效率.对象方法通过对象找到堆中的isa,再找到类再调用方法. 类方法直接调用.
    • 局限性
  3. 无法直接访问类的属性
  4. 不能通过self去调当前类的对象方法
  5. 执行类方法的时候可能还没有对象,那也就访问不了属性.也访问不了对象的方法.
    • 如果方法不需要访问属性,也不需要直接调用当前类的方法,就可以定义为类方法节约空间.
  • 注意的几个问题

    1. 对象方法和对象方法不能重名,类方法之间也不行,但是类方法和对象方法可以同名
    2. 通过类名就是调用类方法,通过对象名就是调用对象方法
    3. 对象方法只能通过对象调用,类方法只能通过类调用.
    4. 类方法可以创建一个对象,访问这个对象的对象属性和对象方法.
    5. 对象方法中可以通过类名来调用类方法.
  • 类方法的规范

    1. 我们写一个类,就要提供一个和类名同名的类方法.返回一个纯洁的对象.对象的属性的值都是默认值.
+ (HMPerson *)person
{
    HMPerson *p1 = [HMPerson new];
    return p1;
}
  1. 为什么这么做,因为这是规范,苹果也这么做.
    NSArray *arr = [NSArray array];
    使用同名的方法.而不是new.
  1. 如果希望创建对象的值是创建者指定的,那就可以为这个类方法带参数
+ (HMPerson *)person;
+ (HMPerson *)personWithName:(NSString *)name andAge:(int)age
{
    HMPerson p1 = [HMPerson new];
    p1->_name = name;
    p1->_age = age;
    return p1;
}
//这个时候创建的时候就可以一起赋值,后面经常会用到.写起来更简单
HMPerson *p2 = [HMPerson personWithName:@"jack" andAge:18];
在方法内部创建对象,并初始化对象的属性,并返回.
  1. 当你创建一个NSAaray对象的时候,有一个aaray方法,N个aarayWith方法.
  2. new 其实是一个类方法.定义在NSObject里面的.创建一个对象.
NSString类
  1. NSString是一个数据类型,保存OC字符串
  2. 实际上是一个类
既然是类拿完成创建的方式应该是
NSString *str0 = [NSString new];
NSString *str1 = [NSString string];
//这个是一个空字符串,里面什么都没有 @"" , 不是nil
//再把字符串存储到这个对象中
  1. 因为NSString是OC中最常用的一个对象
  2. 如果每次都这么创建字符串对象的话,就太累了
  3. 以苹果为我们提供了一个快捷方法 @”“
  4. 这是一个创建NSString对象的简写方式
  5. @”jack” 是一个NSString对象,创建了以后在把字符串的地址保存到str.
  6. %@ 代表打印指针指向的对象.用%p打印就是打印@”jack”这个对象的地址.
    • 既然@”jack”是一个类,那肯定就有方法.str里面应该可以访问.常用的类方法
  7. 类方法stringWithUTF8
将C语言的字符串转换为OC字符串对象.
+ (nullable instancetype)stringWithUUTF8String:(const char*)nullTerminatedCString;
char *name = "杰克;
NSString *str = [NSString stringWithUTF8String:name];
NSLog(@"str = %@",str);
想让用户从控制台输入进来,接到的都是C字符串,这个可以把接收的字符串转换为OC保存起来.


char name[20];
fgets(name,20,stdin);
size_t len = sstrlen(那么);
if(name[len-1] == '\n')
{
    name[len-1] = '\0';
}
p1->name = [NSString stringWithUTF8String:name];
  1. stringWithFormat
将变量拼接乘一个新的OC字符串*******
int age = 19;
NSString *name = @"jack";
要拼接一个新的字符串,不是打印
NSString *str = [NSString stringWithFormat:@"大家好,我叫%@,我今年%d岁",name,age];
  1. 常用的对象方法 计算OC字符串长度
NSUInteger len = [str length];
//是 NSUInteger 其实就是  unsigned long 类型
NSLog(@"%lu",len);
==OC中中文是1个长度!!==
  1. 得到指定下标的字符
NSString *str = @"abc打瞌睡的小男孩!";

unichar ch = [str characterAtIndex:3];
//unichar 是 unsigned short 2个字节.根据情况占的字节不一样,英文一个中文两个.
NSLog(@"ch = %c",ch);
//%c只打印一个字节,所以要用大写的C
NSLog(@"ch = %C",ch);
//打印unichar字符用大C,会自动探测,不会打错.
==OC中一个中文字符占两个字节!!==
  1. 判断两个字符串的内容是否相同**
NSString *str1 = @"jack";
NSString *str2 = @"rose";
//strcmp只能判断C语言的
//str1 == str2 也可以判断,但不要使用,会出问题.
- (NSComparisonResult)compare:(NSString *)string;

NSComparisonResult res = [str1 compare:str2];
1. 返回的是一个枚举值,NSOedereAscending 表示当前字符串str1比str2小.
2. NSOrderedSame 代表一样
3. NSOrdereDescending 当前str1比str2大.
4. 比较的是ASCII码
5. 枚举值烦可以用int接 小是-1,一样是0,大了是1.
  1. 只判断是否相等
BOOL res = [str1 isEqualToString:str2];
不一样是0,一样是1;
匿名对象
  1. 如果函数有返回值,我们可以不使用变量接收返回值,而是直接将函数写在要使用其返回值的地方.
  2. 正常情况下,我们创建对象,是使用1个指针保存了对象的地址.new方法创建,初始化对象,返回地址.
  3. 匿名对象就是没有名字的对象,不用指针去存储对象的地址.
  4. 使用
[HMPerson new]->_name = @"jack";
HMPerson *p = [HMPerson new];
[p goHomeWith:[HMCar new]];
//直接给回家方法里面的参数一个匿名对象.
  1. 因为匿名对象没有名字,所以只能创建出来的时候用一次
  2. 如果一个对象成员你只需要赢一次没就可以使用匿名变量
  3. 如果后面还想用就不能用匿名对象了.
面向对象的三特性:封装
  • 封装:将很多小东西塞在一个大口袋里面.

    1. 对外部屏蔽了内部的实现.
    2. 方便管理
    3. 函数或方法就是一种封装的体现.
    4. 类是一种更高级的封装,将1个类的状态和行为封装在了一个类中,我们只需要直到这个类是干嘛的.
  • 遇到的问题 赋值

    1. 对象的属性赋值的时候,语法上只要赋一个和属性的类型相同的数据都可以
    2. 但是情理上比如年龄int类型不能为负数.应该是0-200的整数,超过这个数据有悖于常理.
    3. 用数据类型又不精确不靠谱,枚举也枚举不完
    4. 解决方案:
    5. 先把类的@public属性去掉,外部就不能访问赋值.不能赋值
    6. 专门设置一个方法为属性赋值,setter
1. 这个方法一定是个对象方法,因为要为属性赋值,所以也没有返回值
2. 方法的名字一定是set开头.再跟上属性名去掉下划线,首字母大写.
3. 方法一定有参数,类型跟属性类型一致.

- (void)setAge:(int)age
{
    if(age >= 0 && age <= 200)
    _age = age;
    //如果不符合要求就做默认处理.
    _age = 18;
}
调用
[p1 setAge:100];
4. 这样就只能使用setter方法来赋值
5. 如果符合逻辑就赋值,否则就不会.
  • 取值getter
这样一来我们的属性也不能通过箭头取出了,所以要再写一个方法取值
1. 要返回属性的值,一定是一个对象方法,所以也一定有返回值
2. 返回值类型和属性类型一致
3. 名字就是属性的名字去掉下划线.
4. 这个方法一定是没有参数的

- (int)age
{
    return _age;
}

int age = [p1 age];

5. 想得到对象的属性值就必须要用对象的getter方法.
  • 只读与只写封装.

    1. 一个属性比如年龄只允许外界取值,就只写getter 不写getter.年龄是自动增长的.就是==只读封装==
    2. 属性的封装只有setter,只能调用setter方法赋值不能取值.就叫做==只写封装==
  • 属性封装的规范
    只要属性需要被外界访问,无论取值赋值有没有逻辑验证,都要为其封装setter或getter.必须封装,不然点语法用不了.==码农==����

- (void)setDog:(HMDog *)dog;
{
    _dog = dog;
}
- (HMDog *)dog
{
    return _dog;
}
类与类之间的关系 ==面试题==
  1. 组合关系 由多个对象组合起来的. 人是有 头 身体 脚 组成的
  2. 依赖关系 人没有手机,需要穿一个手机对象的参数才能打电话 有可能是借来的反正不是他的
  3. 关联关系 人的属性里面有一部手机,可以直接[_phone call] 自己就有一部手机
  4. 继承关系
士兵突击
使用面向对象模拟:士兵开枪,枪射出子弹
名字找类 士兵类 枪类 子弹类
枪属性: 型号,颜色,子弹数量
行为:射击

士兵属性:姓名 兵种 枪
行为:开枪
static关键字
  1. C语言的static 可以修饰局部变量,将局部变量变为静态变量 修饰全局变量,函数
  2. OC中static
    1. static 不能修饰属性和方法
    2. 方法中的局部变量可以修饰,在方法执行完后不会被回收.下次直接用,和c语言修饰局部变量一样
    3. 如果希望方法无论执行多少次,变量只有一个,那么就搞成静态的

self关键字
  • 考虑的问题
    1. 在方法中是可以定义一个和属性名相同的局部变量,这个时候,如果直接使用同名的变量,访问的是局部变量
    2. 如果我们就是要访问属性怎么办呢?
    3. 就是要在1个对象方法中调用当前对象的另外一个对象方法呢?
self关键字
  1. 可以用在对象方法和类方法中
  2. self是一个指针.在对象方法中self指向当前对象.在类方法中self指向当前类.
    • 在对象方法中 使用self
谁调用这个对象方法,谁就是这个对象方法的当前对象.
[p1 sayHi]; 
1. p1 就是当前对象
2. self的值是当前对象的地址
3. %p 的p1 和 self 是相等的
  1. 可以使用self关键字显示的访问当前对象的属性.
  2. 可以使用self关键字来显示的调用当前对象的方法.
  3. 必用场景
{
    1. 有和属性同名的局部变量,要调用属性就必须用self->去调用属性.
    2. 如果想在对象方法中调用当前对象的其他的对象方法必须是用self->.
    3. 如果你重新创建对象,调用的就不是当前对象的方法而是新对象的.
}
4. 选用场景
5. 在方法中如果没有和属性同名的局部变量,这个时候要访问属性名和
6. 属性的名字才以下划线开头,局部变量不要以下划线开头.这样写是不会出现重名的.
  • 在类方法中使用self
    1. 类加载
      当类第一次被访问的时候,就将这个类储存在代码段.一旦存储,直到程序解释才会被释放
    2. 在类方法中self也是一个指针,这个指针指向当前这个类在代码段中的地址
    3. 如何拿到类在代码段中的地址呢?
      1. 查看对象的isa指针
      2. 在类方法中打印self的值
      3. 调用对象的方法class. 也可以得到这个对象所属的类的地址
      4. 调用类的类方法class 也可以得到这个类所在的地址
[p1 class];
//返回p1方法的类在代码段中的值.
[HMPerson class];
//类在代码段中的地址
  1. 我们现在知道:在类方法中, self确实指向当前这个类的.然而有什么用??
    在类方法中,self代表当前这个类.self == HMPerson
    在类方法中,可以使用当前类的地方,完全可以用self代替
在类方法中可以使用self来代替当前类. 比如调用当前类的其他类方法.

声明变量的时候不能用self 他不是类型. HMPerson *p1 的是类型 self是指针不能代替.
[HMPerson new]可以用self代替

继承

  • 多个类具有相同的成员.
    1. 使用复制粘贴缺点:代码冗余.后期维护不好维护.
    2. 继承的目的就是让子类继承父类的成员,而不用自己定义
    3. 步骤
      “`
      @interface 类名 : 父类名

@end

@implementation 类名

@end

在声明类的时候.在类名的后面,冒号后面写上父类的名字

子类就拥有所有父类的成员和方法.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值