Objective-C 学习第三天
封装 一、 什么是错误 一般情况下,错误是指源代码不符合语法规范,然后编译报错 后果: 程序无法编译 什么是Bug? 程序可以编译、链接、执行,但是程序执行的结果不是我们预想的。 解决: 通过调试寻找发生Bug的原因. 异常 程序可以编译、链接、执行,当程序在执行的时候,处于某种特定的条件下,程序就会终止。 后果: 程序立即终止运行 如何处理异常 1). 目的: 为了让程序在执行的时候如果发生了异常而不崩溃 2). 语法 @try{ }@catch(NSException *ex){ } 将有可能发生异常的代码放在@try中. 当@try中的代码在执行的时候,如果发生了异常,不会奔溃,而是立即跳到@catch中执行代码。 当@catch的代码执行完毕后,结束@try...@catch往下执行. 如果没有发生异常, 则跳过@catch往下执行. 3). 当@try中的代码在执行的时候发生了异常,@try块发生异常后面的代码不会被执行. @catch中的代码只有在@try的代码发生异常的时候才会被执行,所以@catch中我们一般情况下写处理异常的代码. @catch的参数NSException *ex通过%@打印出ex指向对象的值,可以拿到发生异常的原因 @try...@catch后面还可以跟1个@finally块 ``` @try{ }@catch(NSException *ex){ }@finally{ } ``` @try...@catch并不是万能的, 并不是所有的运行时错误都可以处理的。 类方法 0). 在一个Target中无法访问另外一个Target中的方法. 1). OC中的方法分为两种 a. 对象方法/实例方法 想要调用对象方法就必须要先创建对象,然后调用 b. 类方法 类方法的调用不依赖于对象. 如果要调用类方法,不需要创建对象 2). 类方法声明 a. 对象方法的声明: 对象方法的声明 - 号 - (返回值)方法名; - (void)sayHi; b. 类方法的声明: 类方法声明使用 + 号 + (返回值类型)方法名; 3). 调用 a. 对象方法: 先创建对象再通过对象名来调用 b. 类方法: 不需要创建对象, 直接使用类名来调用 [类名 类方法名]; 4). 分析类方法和对象方法 a. 类方法的特点 a). 节约空间 b). 提高效率 5). 在类方法中不能直接访问属性 因为属性只有在对象创建的时候才会创建在对象之中,而类方法在执行的时候有可能还没有对象。 虽然不能直接访问属性,但是我们可以在类方法中创建一个对象访问这个对象 a. 属性是在对象创建的时候跟随着对象一起创建在对象之中 b. 类第1次在访问时回做类加载 在类方法中不能使用self来调用其他对象方法 [self 方法名];//调用当前类型的方法 在对象方法当中可以调用类方法 [类名 方法名]; 什么时候可以将方法定义为类方法 如果方法不需要直接访问属性,也不需要直接调用其他的对象方法,可以定义为类方法 关于类方法的规范. 1). 如果我们写一个类,要求为这个类提供一个与类名同名的方法,这个方法创建 创建一个纯净的对象返回. 苹果和第三方都遵守这个规范 (Person *)person; 2). 如果希望创建的对象的属性的值由调用者指定,那么这个类方法带参数. 类名WithXXX:... (Person *)personWithName:(NSString *)name andAge:(int)age; 二、 NSString 是1个数据类型,用来保存OC字符串的 其实NSString是Foundation框架中的1个类,作用存储OC字符串.所以OC中的字符串本质上是用NSString对象来存储的. 完整的标准的创建NSString对象的方式 NSString *str = [NSString new]; NSString *str1 = [NSString string]; 这种方式创建的字符串是空字符串 @"" 但是NSString是最常用的1个对象, 所以OC使用了1种更为简单的方式来创建对象,直接使用@来表示1个OC字符串. NSString *str = @"jack"; @"jack" 本质上是一个NSString对象,str是这个对象的地址. NSString最常用的类方法 1). + (instancetype)stringWithUTF8String:(const char *)nullTerminatedCString instancetype作为返回值,代表返回当前这个类的对象 char *str0 = "rost"; NSString *str1 = [NSString stringWithUTF8String:str0]; 2). + (instancetype)stringWithFormat:(NSString *)format, ...使用频率非常高 作用: 拼接1个字符串对象,使用变量或者其他数据拼接成OC字符串 int age = 19; NSString *name = @"小明"; [NSString stringWithFormat: @"大家好,我叫%@, 我今年%d岁.",name,age] 最长用的对象方法 1). length方法, 返回值NSUInteger,计算字符串长度 NSString *str = @"itcast"; NSUInteger len = [str length]; 2). 得到字符串中指定下标的字符 (unichar)characterAtIndex:(NSUInteger)index; 返回值是unichar, 其实就是unsigned short,占据两个字节. 如果要输出unichar变两个的值使用%C NSString *str = @"itcast"; unichar ch = [str characterAtIndex:2]; 3). 判断两个字符串是否相同 a. 判断两个字符串内容是否相同, 不要使用==判断 b. 判断相等的方式 - (BOOL)isEqualToString:(NSString *)aString; 判断两个字符串是否相等应该使用上面的方法来判断. NSString *str1 = @"jack"; NSString *str2 = @"jack"; [str1 isEqualToString: str2]; 4). 判断两个字符串大小 - (NSComparisonResult)compare:(NSString *)string; NSComparisonResult是个枚举, 完全可以使用int来接收返回值. NSString *str1 = @"jack"; NSString *str2 = @"jack"; [str1 compare: str2]; 匿名对象 1). 之前创建对象的做法: Person *p1 = [Person new]; 让1个指针指向1个对象 2). 匿名对象 没有名字的对象, 如果我们创建一个对象,没有用1个指针存储这个对象的地址,也就是没有任何指针指向这个对象,那么这个对象就叫做匿名对象. 3). 如何使用1个匿名对象 [Person new]->_name = @"jack"; [[Person new] sayHi]; 4). 注意点 a. 匿名对象只能使用一次 b. 每次创建匿名对象都是不同的对象 5). 使用情况 a. 某个对象只会被使用一次 b. 如果方法的参数是一次对象, 并且这个对象调用者不会使用 三、 面向对象的三大特征: 封装、继承、多态 封装: a. 函数就是封装的体现 b. 类就是更高级别的封装 好处: ->屏蔽内部的实现, 外界不需要知道内部是如何实现的 ->方便操作 继承: 多态: setter封装 1). 将属性的@public去掉, 一旦写上@public就可以直接访问对象的这个属性. 为类提供1个方法,专门为这个属性赋值,这个方法我们叫做setter。 a. 这个方法一定是1个对象方法 b. 没有返回值 c. 这个方法的名称必须以set开头, 跟上去掉下划线首字母大写的属性名. d. 这个方法一定是有参数的, 参数的类型和属性的类型一致, 参数的名称和属性的名称一致(去掉下划线) e. 在方法的实现中,检测传入的数据是否符合要求 // 声明 @interface Person : NSObject{ int _age; } - (void) setAge(int age); @end // 实现 @implementation Person - (void) setAge(int age){ _age = age; } @end // 调用 Person *p = [Person new]; [p setAge:10]; getter封装 1). 用来取出属性的值 a. 这个方法一定是一个对象方法 b. 这个方法返回值类型和属性的类型一致 c. 这个方法的名称直接属性的名称(去掉下划线) d. 这个方法没有参数 e. 外界想要获取这个值,直接调用方法即可. // 声明 @interface Person : NSObject{ int _age; } - (void) setAge(int age); - (int)age(); @end // 实现 @implementation Person - (void) setAge(int age){ // 可以做验证 _age = age; } - (int)age(){ return _age; } @end // 调用 Person *p = [Person new]; [p setAge:10]; [p age]; 注意 属性的@public一定要去掉 判断参数的值是否符合逻辑 getter/setter方法名极度不规范 什么时候需要封装getter/setter 1). 只要属性需要被外界访问就要回这个属性封装setter和getter, 就算赋值或者取值的时候没有任何逻辑验证 2). 如果属性只在内部访问, 不需要封装getter/setter 只读只写封装 只读封装: 为属性封装的时候,只提供getter属性 只写封装: 为属性封装的时候,只提供setter属性 对象之间的关系 1). 组合关系: 一个类是由其他几个类组合而成的 2). 依赖关系: 一个对象的方法的参数是另外一个类 a. 耦合度: 当一个类修改之后另一个类无法使用,叫高耦合 b. 低耦合:当一个类修改之后另一个类正常使用,叫高耦合 c. 高内聚: 一个对象仅仅只做自己相关的事情 d. 单一职责原则: 一个类只做自己的事情 3). 关联关系: 两个类之间语义级别的一种强依赖关系, 拥有关系 4). 继承关系: