------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
OC回顾-对象特性
一、类方法的学习引入
思考&实现:
设计一个计算器类
实现两个数的+ - * /的计算。
//主函数
#import <Foundation/Foundation.h>
#import "Calculator.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Calculator * c=[Calculator new];
int result = [c add:12 andNum2:24];
NSLog(@"%d",result);
}
return 0;
}
//Calculator.h
//类的声明
#import <Foundation/Foundation.h>
@interface Calculator : NSObject
-(int)add:(int) num1 andNum2:(int) num2;
-(int)jian:(int) num1 andNum2:(int) num2;
-(int)cheng:(int) num1 andNum2:(int) num2;
-(float)chu:(int) num1 andNum2:(int) num2;
@end
//类的实现
#import "Calculator.h"
@implementation Calculator
-(int)add:(int) num1 andNum2:(int) num2{
return num1+num2;
}
-(int)jian:(int) num1 andNum2:(int) num2{
return num1-num2;
}
-(int)cheng:(int) num1 andNum2:(int) num2{
return num1*num2;
}
-(float)chu:(int) num1 andNum2:(int) num2{
return num1/(float)num2;
}
@end
二、类方法概述及定义方法
1、类方法概述
+表示类方法,就是类调用方法,不用创建一个实例(对象)。
定义格式:
+(返回值类型)方法名:(参数类型)参数名;
2、类方法的调用
[类名称 类方法名称];
三、类方法注意事项
1、类方法可以和实例方法同名,这个不影响使用。因为两者类型不同。
2、类方法也可以是从父类继承而来,子类可以重写类方法。
3、类方法和对象方法一样在interface里声明,在implementation中实现。
4、类方法只能被类调用执行,向对象发送类方法是不能被执行的。
5、在类方法里使用了self,这个self执行的类对象class object而不是实例对象instance object。
四、类方法易犯的错误
1、类方法的优点:
1)节省内存空间(不用创建实例对象)
2)提高了效率
3)作为工具方法
2、类方法的易犯错误
在类方法中不能使用类的成员变量。
在对象方法中可以使用类的成员变量。
3、类方法与对象方法的比较
1)对象方法:
以 - 开头
可以使用成员变量
用对象调用对象方法
对象方法可以调用当前对象或者其他对象的方法
2)类方法:
以+开头
不可以使用成员变量
用类名调用类方法
类方法可以调用对象方法和类方法
类方法不可以调用自身,会造成死循环
几点注意:
在本类中:
1、本类方法之间的调用使用self;self代表类。
2、本类对象方法之间的调用也是用self;self代表对象。
3、本类的类方法和对象方法之间不能使用self调用。
不是本类中:
1、类方法或者对象方法想要调用别的类中的对象方法的话,可以将对象作为参数传递过来。
2、类方法或者对象方法想要调用别的类方法的话,不需要传参数,直接用类名就可以。
五、类方法应用场景
如果我们调用一个方法,该方法中不需要使用成员变量那么我们可以将该方法声明为类方法。
六、匿名对象的概念及使用
1、匿名对象的概念
不使用对象,而是通过[类名 new]代替对象的方法。
当对象的方法只调用依次,可以使用匿名对象来完成。
使用匿名类的方法:
1)使用匿名类访问实例变量
只能访问一次,以后再访问,实际上就是访问新的空间。
2、使用匿名类可以调用方法。
3、匿名类可以作为方法的参数
匿名类的优缺点:
优点:可以简化代码,方便方法调用
缺点:匿名对象实例化以后,只能正确的使用成员变量一次。
4、alloc和init
alloc和init分别把分配内存和初始化的工作分开。这样更加灵活,可以自行初始化对象的成员变量值
而不像new每次都初始化为0 。
new是把分配内存和初始化的工作一起完成了。
七、封装的概念及原理
面向对象的特性之一:封装(OC最小的封装体就是函数)
封装:
是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。
封装的好处:
1、将变化隔离。(不管里面怎么变,使用者不需要知道)
2、便于使用(使用者指需要按照一定的方法使用就可以了)
3、提高重用性(任何人都可以对已经封装好的功能进行操作)
4、提高安全性(由于暴露给使用者的只是一些外在的操作环节,而不是里面本质的东西,所以就提高了对程序的安全性)
封装的原则:
将不需要对外提供的内容隐藏起来。
把属性都隐藏,提供公共方法对其访问。
为什么要封装
不封装的缺点:
当一个类把自己的属性暴露给外部的时候,那么该类就失去对属性的管理权。
封装的原理
实例变量默认只能被当前类的对象方法访问。
八、封装的实现步骤
定义设置实例变量(setter)方法和访问实例变量(getter)的方法
1、setter方法(设置器)
使用set方法来为对象提供成员变量的值,在set方法的内部也可以对一些不合理的赋值进行筛选过滤。
set方法的作用:位外界提供一个设置成员变量值的方法。
命名规范:
1)必须set开头,set后跟的是却掉下划线的实例变量名并且首字母大写。
2)一定有参数
3)不能有返回值
4)一定是对象方法
5)形参名一般是去掉下划线的实例变量名
6)形参类型和实例变量类型一致
7)形参名一般不能和成员变量名相同,如果相同则通过self访问成员变量
8)在set方法中一定得给实例变量赋值
set方法的好处:
1)不让数据暴露在外,保证了数据的安全性
2)对设置的数据进行过滤
2、getter方法(访问器)
get方法的作用:为调用者返回对象内部的成员变量
命名规范:
1)一定是一个对象方法
2)一定有返回值,返回值的类型和实例变量的类型要一致
3)get方法的方法名是去掉下划线的实例变量名
4)一定没有参数
5)get方法的实现中,一定是返回实例变量值
注意:
1)如果是只读的数据,可以指提供get方法,而不提供set方法
2)成员变量名以下划线开头,get方法名不需要下划线。
封装的应用:股票K线计算
练习:
设计一个K线类
最低价格(可读可写)
最高价格(可读可写)
平均价格(只读)
//主函数
#import <Foundation/Foundation.h>
#import "KLine.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
KLine *kline=[KLine new];
[kline setMax:80.5f];
[kline setMin:40.6f];
NSLog(@"平均值是:%.2f",[kline avg]);
}
return 0;
}
//类的声明
#import <Foundation/Foundation.h>
@interface KLine : NSObject
{
float _max;
float _min;
float _avg;
}
-(void)setMax:(float) max;
-(void)setMin:(float) min;
-(float)max;
-(float)min;
-(float)avg;
@end
//类的实现
#import "KLine.h"
@implementation KLine
-(void)setMax:(float) max{
_max=max;
_avg=(_max+_min)/2;
}
-(void)setMin:(float) min{
_min=min;
_avg=(_max+_min)/2;
}
-(float)max{
return _max;
}
-(float)min{
return _min;
}
-(float)avg{
return _avg;
}
@end
运行结果:
2015-10-23 07:45:51.923 11-封装应用:股票k线计算[901:94009] 平均值是:60.55
Program ended with exit code: 0
九、组合模式
1、组合模式定义
把具有相同基类类型的对象组合到属性结构中,以表示“部分—整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
组合模式使得树形结构中的每个节点都具有相同的抽象接口,整个结构可作为一个统一的抽象结构使用,而不暴露其内部表示。每个节点的任何操作,可以通过抽象基类中定义的相同接口来进行。
2、
在Cocoa Touch框架中,UIView对象被组合成一个树形结构,UIView对象可以包含其他的UIView对象。这种组合方式便于统一用于时间处理和动作消息。
3、组合模式的优点
客户端可以统一的使用组合对象或单个对象,而不组合结构不暴露其内部表示。
可以很容易在组合体内加入具有相同抽象类型的对象。
客户端不必因为加入了新的对象而更改代码。
十、依赖关系和关联关系
1、依赖关系
A对象作为B对象的局部变量或是方法形参是,B依赖A,这时候我们称A与B之间存在一种依赖关系。
/*
美女用手机给土豪打电话、发短息
*/
#import <Foundation/Foundation.h>
#import "Girl.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Phone *phone=[Phone new];
Girl *girl=[Girl new];
[girl callPhone:phone];
[girl sentMessage:phone];
}
return 0;
}
//Phone类的声明
// Phone.h
#import <Foundation/Foundation.h>
@interface Phone : NSObject
{
NSString *_phoneNum;
}
-(void)setPhoneNum:(NSString *) phoneNum;
-(void)call:(Phone *) phone;
-(void)message:(Phone *) phone;
@end
//Phone类的实现
// Phone.m
#import "Phone.h"
@implementation Phone
-(void)setPhoneNum:(NSString *) phoneNum{
_phoneNum=phoneNum;
}
-(void)call:(Phone *) phone{
NSLog(@"美女正在和号码%@打电话",phone->_phoneNum);
}
-(void)message:(Phone *) phone{
NSLog(@"美女正在给号码%@发短信!",phone->_phoneNum);
}
@end
//Girl类的声明
// Girl.h
#import <Foundation/Foundation.h>
#import "Phone.h"
@interface Girl : NSObject
-(void)callPhone:(Phone *) phone;
-(void)sentMessage:(Phone *) phone;
@end
//Girl类的实现
// Girl.m
#import "Girl.h"
@implementation Girl
-(void)callPhone:(Phone *) phone{
[phone setPhoneNum:@"18688888888"];
[phone call:phone];
}
-(void)sentMessage:(Phone *) phone{
[phone setPhoneNum:@"18688888888"];
[phone message:phone];
}
@end
运行结果:
2015-10-23 07:44:46.935 13-依赖关系[891:93461] 美女正在和号码18688888888打电话
2015-10-23 07:44:46.936 13-依赖关系[891:93461] 美女正在给号码18688888888发短信!
Program ended with exit code: 0
2、关联关系
当一个对象拥有另外一个对象的时候。
当B对象为A对象的成员变量的时候,B对象与A对象之间存在一种关联关系。
关联关系是面向对象中最常用的一种关系
关联关系的耦合度要高于依赖关系。
面向对象设计中:
耦合度:当修改一个对象的时候,对另外一个对象的影响程度
低耦合:当修改一个对象时对其他对象影响比较小
高内聚:一个队形仅仅做自己相关的事情
面向对象设计原则:单一职责原则
思考&实现:
用关联关系实现,美女有一台iPad,并且用iPad听音乐的过程。
/*
思考&实现:
用关联关系实现,美女有一台iPad,并且用iPad听音乐的过程。
*/
#import <Foundation/Foundation.h>
#import "Girl.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Ipad *ipad=[Ipad new];
[ipad setName:@"iPadAir"];
Girl *girl=[Girl new];
[girl setIpad:ipad];
[girl useIpad];
}
return 0;
}
//Girl类的声明
// Girl.h
#import <Foundation/Foundation.h>
#import "Ipad.h"
@interface Girl : NSObject
{
NSString *_name;
Ipad *_ipad;
}
-(void)setName:(NSString *) name;
-(void)setIpad:(Ipad *) ipad;
-(void)useIpad;
@end
//Girl类的实现
// Girl.m
#import "Girl.h"
@implementation Girl
-(void)setName:(NSString *) name{
_name=name;
}
-(void)setIpad:(Ipad *) ipad{
_ipad=ipad;
}
-(void)useIpad{
[_ipad playMusic];
}
@end
//Ipad类的声明
// Ipad.h
#import <Foundation/Foundation.h>
@interface Ipad : NSObject
{
NSString *_name;
}
-(void)setName:(NSString *) name;
-(void)playMusic;
@end
//Ipad类的实现
// Ipad.m
#import "Ipad.h"
@implementation Ipad
-(void)setName:(NSString *) name{
_name=name;
}
-(void)playMusic{
NSLog(@"美女正在用%@听歌",_name);
}
@end
运行结果:
2015-10-23 07:48:36.373 14-关联关系[913:95969] 美女正在用iPadAir听歌
Program ended with exit code: 0