IOS开发学习笔记010
面向对象的三大特性
1、封装
2、继承
3、多态
一、封装
将类内部的属性保护起来,在外部不能直接访问,那么如果需要访问怎么办呢?
OC提供了set方法来对成员变量进行访问
set方法
1、作用:提供一个方法给外界设置age属性的值
2、命名规范
方法名必须是set开头
set后面跟上成员变量的名称,成员变量首字母必须大写
返回值一定是void
一定要接收一个参数,并且和成员变量类型一致
形参名不能和成员变量名一样
声明
- (void)setAge:(int)newAge;//声明
实现
1 - (void)setAge:(int)newAge//set方法实现 2 { 3 if(newAge <= 0)//如果小于0岁就赋值为1 4 { 5 newAge = 1; 6 } 7 age = newAge;//设置年龄 8 }
使用
1 Student *p = [Student new];//新建对象 2 [p setAge:20];//设置属性 3 [p study];//调用方法
get方法
1、作用:返回对象内部的成员变量
2、命名规范:
肯定有返回值,返回类型和成员变量一致
方法名和成员变量名一样
不需要接收参数
声明
- (int)age;//
实现
1 - (int)age// 2 { 3 return age; 4 }
使用
1 NSLog(@"%d岁的学生在学习!",[p age]);
成员变量的使用
命名规范:
成员变量都以下划线 _ 开头
可以跟get方法的名称区分开
可以跟其他局部变量区分开,一看到下划线开头的变量,肯定是成员变量
1 @interface Student : NSObject 2 { 3 //@public 4 //成员变量 5 //让成员变量和get方法区分开,成员变量都要加_ 6 int _no; 7 int _age; 8 Sex _sex; 9 } 10 11 @end
练习1
1 #import <Foundation/Foundation.h> 2 3 //成绩类 4 /* 5 C成绩(读写) 6 OC成绩(读写) 7 平均分(只读) 8 总分(只读) 9 */ 10 //类的声明 11 @interface Score : NSObject 12 { 13 int _cScore;//c成绩 14 int _ocScore;//oc成绩 15 16 int _totalScore;//总分 17 int _averageScore;//平均分 18 } 19 20 //方法声明 21 //set 22 - (void)setCScore:(int)newCScore; 23 - (void)setOcScore:(int)newOcScore; 24 25 //get 26 - (int)cScore; 27 - (int)ocScore; 28 - (int)totalScore; 29 - (int)averageScore; 30 31 @end 32 33 34 35 //类的实现 36 @implementation Score 37 //方法实现 38 - (void)setCScore:(int)newCScore 39 { 40 _cScore = newCScore; 41 //计算总分和平均分 42 _totalScore = _cScore + _ocScore; 43 _averageScore = _totalScore/2; 44 } 45 - (void)setOcScore:(int)newOcScore 46 { 47 _ocScore = newOcScore; 48 //计算总分和平均分 49 _totalScore = _cScore + _ocScore; 50 _averageScore = _totalScore/2; 51 } 52 53 - (int)cScore 54 { 55 return _cScore; 56 } 57 - (int)ocScore 58 { 59 return _ocScore; 60 } 61 - (int)totalScore 62 { 63 return _totalScore; 64 } 65 - (int)averageScore 66 { 67 return _averageScore; 68 } 69 @end 70 71 72 int main() 73 { 74 Score *p = [Score new];//新建对象 75 [p setCScore:100];//set方法 76 [p setOcScore:90];//set方法 77 78 NSLog(@"总分:%d",[p totalScore]); 79 80 NSLog(@"平均分:%d",[p averageScore]); 81 82 return 0; 83 }
OC弱语法
如果调用不存在的方法,那么在编译和链接时都不会报错,最多有一个警告。只有在运行时才回出错。
unrecognized selector sent to instance 0x0000034034C0
给对象发送的消息不能识别
OC只有在运行过程中才会检测对象有没有实现相应的方法。
类方法
1、以+开头
2、通过类名调用的方法。
3、类方法不能访问成员变量
4、类方法和对象方法可以重名
5、使用场合:当不需要访问成员变量时尽量用类方法
声明
+ (void)printClassName;//
实现
1 + (void)printClassName// 2 { 3 NSLog(@"class name is Person"); 4 }
使用
[Person printClassName];//类方法的调用,直接使用类名
工具类
没有成员变量的类,里面的方法全是类方法。
示例
1 #import <Foundation/Foundation.h> 2 /* 3 工具类 4 没有成员变量 5 所有方法全是类方法 6 */ 7 //类声明 8 @interface JiSuanQi : NSObject 9 10 + (void)printClassName;//类方法 11 12 + (int)sumOfSum1:(int)sum1 andSum2:(int)sum2;//类方法 13 14 @end 15 //类的实现 16 @implementation JiSuanQi 17 + (void)printClassName 18 { 19 NSLog(@"class name is JiSuanQi"); 20 21 } 22 + (int)sumOfSum1:(int)sum1 andSum2:(int)sum2 23 { 24 return sum1 + sum2; 25 } 26 27 @end 28 29 int main() 30 { 31 32 [JiSuanQi printClassName];//类方法的调用,直接使用类名 33 int res = [JiSuanQi sumOfSum1:10 andSum2:20]; 34 NSLog(@"%d",res); 35 return 0; 36 }
self关键字
谁调用,self代表谁。
如果用对象调用,就代表对象,如果是类调用,就代表类。
成员变量和局部变量同名
当成员变量和局部变量同名时,采取就近原则,访问的是局部变量
用self访问成员变量,区分同名的局部变量
self出现的位置:
所有的OC方法中(对象方法\类方法),不能出现在函数
作用方式:
使用 "self->成员变量名" 访问当前方法调用的成员变量
使用 "[self 方法名];" 来调用方法(对象方法\类方法)
1 - (void)setAge:(int)newAge 2 { 3 _age = newAge; 4 5 int _age = 10;//局部变量与成员变量同名时,如果需要使用成员变量,则需要使用self关键字 6 NSLog(@"age is %d",self->_age);//self 是一个指指针,指向调用的对象 7 }
小练习
设计Car类,一个对象方法跟其他车子比较车速,返回速度差,一个类方法比较两辆车的车速,返回速度差
1 #import <Foundation/Foundation.h> 2 3 //类的声明 4 @interface Car : NSObject 5 { 6 int _speed;//速度 7 } 8 - (void)setSpeed:(int)newSpeed; 9 - (int)speed; 10 //对象方法 11 /* 12 作用:比较两辆车的速度大小,返回差值 13 方法名:differenceSpeedWithOtherCar: 14 参数:(Car *)otherCar 15 返回值:int 16 */ 17 - (int)differenceSpeedWithOtherCar:(Car *)otherCar; 18 19 //类方法 20 /* 21 作用:比较两辆车的速度大小,返回差值 22 方法名:differenceSpeedWithCar1: : 23 参数:(Car *)Car1 (Car *)Car2 24 返回值:int 25 */ 26 + (int)differenceSpeedWithCar1:(Car *)Car1 andCar2:(Car *)Car2; 27 @end 28 29 //类的实现 30 @implementation Car 31 //对象方法的实现 32 - (void)setSpeed:(int)newSpeed 33 { 34 _speed = newSpeed; 35 } 36 37 - (int)speed 38 { 39 return _speed; 40 } 41 42 //对象方法 43 - (int)differenceSpeedWithOtherCar:(Car *)otherCar 44 { 45 return [self speed] - [otherCar speed];//self指向调用者也就是本对象 46 } 47 48 //类方法 49 50 + (int)differenceSpeedWithCar1:(Car *)Car1 andCar2:(Car *)Car2; 51 { 52 return [Car1 speed] - [Car2 speed];//通过类调用的话,只能传进来两个参数,因为默认成员变量是0,没有任何实际意义。 53 } 54 55 @end 56 57 int main() 58 { 59 Car *p1 = [Car new]; 60 [p1 setSpeed:300]; 61 62 Car *p2 = [Car new]; 63 [p2 setSpeed:200]; 64 65 Car *p3 = [Car new]; 66 [p3 setSpeed:90]; 67 68 int res = [p1 differenceSpeedWithOtherCar:p2];//使用对象调用方法 69 NSLog(@"%d",res); 70 71 res = [Car differenceSpeedWithCar1:p1 andCar2:p3];//使用类调用方法 72 NSLog(@"%d",res); 73 return 0; 74 }
二、继承
子类从父类继承一些公共属性和方法。
不允许子类和父类拥有同名的成员变量。
方法可以和父类的方法同名(重写),调用过程是先找子类的,再找父类的。
继承的使用场合
1、当两个类拥有相同的属性和方法时,可以将相同的东西抽象到一个类中
2、当类a中含有类B所需的全部或部分属性和方法时,可以让B继承A
继承与组合区别
继承:A 是 B;
组合:A 拥有B;
示例
1 #import <Foundation/Foundation.h> 2 3 //Animal类的声明 4 @interface Animal : NSObject 5 { 6 int _age;//年龄 7 double _weight;//体重 8 } 9 //对象方法 10 - (void)setAge:(int)newAge; 11 - (int)age; 12 13 - (void)setWeight:(int)newWeight; 14 - (double)weight; 15 16 - (void)run; 17 @end 18 19 20 //Animal类的实现 21 @implementation Animal 22 //方法实现 23 - (void)setAge:(int)newAge 24 { 25 _age = newAge; 26 } 27 - (int)age 28 { 29 return _age; 30 } 31 32 - (void)setWeight:(int)newWeight 33 { 34 _weight = newWeight; 35 } 36 - (double)weight 37 { 38 return _weight; 39 } 40 41 - (void)run 42 { 43 NSLog(@"动物在奔跑!"); 44 } 45 46 @end 47 48 49 50 51 52 //Dog类的声明 53 @interface Dog : Animal 54 { 55 //int _age;//子类不能和父类的成员变量重名 56 int gouPai;//狗牌 57 } 58 //对象方法 59 - (void)run;//重写父类的方法 60 @end 61 62 63 //Dog类的实现 64 @implementation Dog 65 //方法实现 66 - (void)run 67 { 68 NSLog(@"Dog在奔跑!"); 69 } 70 71 @end 72 73 //Cat类的声明 74 @interface Cat : Animal 75 { 76 77 } 78 //对象方法 79 80 @end 81 82 83 //Cat类的实现 84 @implementation Cat 85 //方法实现 86 87 88 @end 89 90 int main() 91 { 92 Dog *d = [Dog new]; 93 [d setAge:4]; 94 [d run];//子类的run会覆盖父类的run方法 95 NSLog(@"%d",[d age]); 96 97 return 0; 98 }
super关键字
如果在子类中想访问父类的方法(对象方法和类方法都可以),可以使用关键字super进行调用 ;
[super walk];//具体是对象方法还是类方法取决于调用时所处于的环境。
使用场景:子类使用父类的方法时想保留父类的一些操作
1 //方法实现 2 - (void)run 3 { 4 NSLog(@"Dog在奔跑!"); 5 6 [super run];//super 关键字,调用父类的方法 7 }
三、多态
父类指针指向子类对象:多态
1、没有继承就没有多态
2、父指针指向子类对象
3、优点:函数/方法传入父指针,则在调用时可以传入子类指针和父类指针
4、缺点:父类类型的变量,不能直接调用子类特有的方法
代码示例
1 #import <Foundation/Foundation.h> 2 /* 3 多态 4 5 */ 6 7 8 //Animal类的声明 9 @interface Animal : NSObject 10 { 11 // int _age;//年龄 12 //double _weight;//体重 13 } 14 //对象方法 15 16 - (void)eat; 17 @end 18 19 20 //Animal类的实现 21 @implementation Animal 22 //方法实现 23 - (void)eat 24 { 25 NSLog(@"吃吃吃!"); 26 } 27 28 @end 29 30 31 32 33 34 //Dog类的声明 35 @interface Dog : Animal 36 { 37 //int _age;//子类不能和父类的成员变量重名 38 //int gouPai;//狗牌 39 } 40 //对象方法 41 - (void)eat;//重写父类的方法 42 @end 43 44 45 //Dog类的实现 46 @implementation Dog 47 //方法实现 48 - (void)eat 49 { 50 NSLog(@"Dog在吃吃吃!"); 51 52 // [super eat];//super 关键字,调用父类的方法 53 } 54 55 @end 56 57 58 //Cat类的声明 59 @interface Cat : Animal 60 { 61 //int _age;//子类不能和父类的成员变量重名 62 //int gouPai;//狗牌 63 } 64 //对象方法 65 - (void)eat;//重写父类的方法 66 - (void)run; 67 @end 68 69 70 //Dog类的实现 71 @implementation Cat 72 //方法实现 73 - (void)eat 74 { 75 NSLog(@"Cat在吃吃吃!"); 76 77 // [super eat];//super 关键字,调用父类的方法 78 } 79 - (void)run 80 { 81 NSLog(@"Cat在跑!"); 82 } 83 @end 84 85 86 int main() 87 { 88 //Dog *d = [Dog new]; 89 90 //父类指针指向子类对象:多态 91 Animal *a = [Dog new]; 92 //[a run];//父类指针调用子类的特有方法,会有警告 93 94 95 Dog *d = (Dog *)a;//可以强制转换,调用子类特有的方法 96 [d eat]; 97 98 99 100 return 0; 101 }
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。