OC从入门到精通-2.三大特性(封装,继承,多态)
来源:互联网 发布:js 控制class active 编辑:程序博客网 时间:2024/06/13 07:30
OC三大特性
- 封装
- 继承
- 多态
封装
set和get方法
成员变量命名规范
弱语法
类方法的使用
self的一些用法
用法1:self用来访问成员变量
//先看一段没使用self的代码#import <Foundation/Foundation.h>@interface Person : NSObject{ int _age;}- (void)setAge;- (void)age;- (void)test;@end@implementation Person- (void)setAge:(int)age{ //_age是成员变量 _age=age;}- (int)getAge{ return _age;}- (void)test{ int _age=20; //这是一个局部变量 NSLog(@"成员变量_age的值为%d",_age);}@endint main(int argc, const char * argv[]) { Person *p=[Person new]; [p setAge:10]; [p getAge]; [p test]; return 0;}
输出结果为:
2016-03-25 11:43:15.326 3-25-3[39932:2019323]成员变量_age的值为20Program ended with exit code: 0
修改上述test方法的代码,如下
- (void)test{ //self :指向调用它的指针 int _age=20; //self->age用来调用当前对象的成员变量,局部变量不会影响它 NSLog(@"成员变量_age的值为%d",self->_age);}
输出结果为:
2016-03-25 11:45:36.209 3-25-3[39942:2021207] 成员变量_age的值为10Program ended with exit code: 0
//self :指向调用它的指针
2.self用来访问对象方法 or 类方法
//self的使用#import <Foundation/Foundation.h>@interface Person : NSObject{ int _age;}- (void)setAge:(int)age;- (int)age;- (void)test;- (void)eat;- (void)run;@end@implementation Person- (void)setAge:(int)age{ //_age是成员变量 _age=age;}- (int)age{ return _age;}- (void)eat{ NSLog(@"先吃饭");}- (void)run{ [self eat]; //可以调用其他对象方法 or 类方法 NSLog(@"后跑步");}- (void)test{ //int _age=20; NSLog(@"成员变量_age的值为%d",self->_age);}@endint main(int argc, const char * argv[]) { Person *p=[Person new]; [p run]; return 0;}
输出结果:
2016-03-25 11:50:16.441 3-25-self2[39968:2024515] 先吃饭2016-03-25 11:50:16.442 3-25-self2[39968:2024515] 后跑步Program ended with exit code: 0
3.self指向调用它的指针,本身就是一个指针
下面来看一段代码,估计下它的输出结果是什么
//self的使用#import <Foundation/Foundation.h>@interface Person : NSObject{}- (void)test;+ (void)test;- (void)test1;+ (void)test1;- (void)rest1;+ (void)rest2;@end@implementation Person- (void)test{ NSLog(@" - test");}+ (void)test{ NSLog(@" + test");}- (void)test1{ [self test]; //-test}+ (void)test1{ [self test]; //+test}@endint main(int argc, const char * argv[]) { Person *p =[Person new]; [p test1]; return 0;}
输出为:
- test
这里的[p test1]中的p是一个Person对象,所以首先调用 - test1 对象方法,- test1 对象方法中的self 指向的是调用它的指针,也就是对象p,所以self 就会调用- test() 对象方法
如果把上述main 方法修改如下:
int main(int argc, const char * argv[]) { //Person *p =[Person new]; //[p test1]; [Person test1];
输出则为:
+ test
这里的[Person test1]中的Person是一个类,所以首先调用 + test1 类方法,+ test1 类方法中的self 指向的是调用它的指针,也就是类Person,所以self 就会调用+ test() 类方法
2.继承
类A继承类B,则类B的所有属性,类A都将获得。
继承的基本语法
//// main.m// 继承1#import <Foundation/Foundation.h>//父类 People类,代表所有人类@interface People : NSObject{ int _age; double _weight;}- (void)setAge:(int)age;- (int)age;- (void)setWeight:(double)weight;- (double)weight;@end@implementation People- (void)setAge:(int)age{ _age=age;}- (int)age{ return _age;}- (void)setWeight:(double)weight{ _weight=weight;}- (double)weight{ return _weight;}@end/****Student****///Student 继承了People,相当于拥有了People里的所以成员变量和方法@interface Student : People@end@implementation Student@end/****Teacher****/@interface Teacher : People@end@implementation Teacher@endint main(int argc, const char * argv[]) { Student *s=[Student new]; [s setAge:20]; NSLog(@"The age of Student is %d", [s age]); Teacher *t=[Teacher new]; [t setWeight:50.2]; NSLog(@"The age of Teacher is %f", [t weight]); return 0;}
输出结果为:
The age of Student is 20The age of Teacher is 50.200000
子类继承父类,那么子类可以访问父类的所以成员变量和方法。
上图显示的正是代码中的类继承关系。这不是标准的类图,该图主要是帮助理解,箭头所指的是继承关系。继承后,子类拥有父类的方法。所以在Student 和Teacher方法中没有写任何方法,却可以调用set 和get 方法。
继承中的成员变量
对上面代码的Student 作如下修改
@interface Student : People int _age; int _num;@end
运行时会报错!将其注释//int age是可以运行的。
可以看出
- OC中不允许子类和父类有相同的成员变量
- OC中子类可以添加父类中没有的成员变量或方法
继承中的方法
优先检查子类中重写的方法,如果没有再检查父类中的方法
看如下代码:
//// main.m// 继承1#import <Foundation/Foundation.h>//父类 People类,代表所有人类@interface People : NSObject{ int _age; double _weight;}- (void)run;@end@implementation People- (void)run{ NSLog(@"People在跑");}@end/****Student****///Student 继承了People,相当于拥有了People里的所以成员变量和方法@interface Student : People//定义自己的run方法//父类中已经有了run方法了,所以这里就是“重写”父类方法- (void)run;@end@implementation Student- (void)run{ NSLog(@"Student在跑");}@endint main(int argc, const char * argv[]) { Student *s=[Student new]; [s run]; return 0;}
输出结果为:
Student在跑Program ended with exit code: 0
优先检查子类中重写的方法,如果没有再检查父类中的方法
其实这个过程很好理解,每个对象里面有一个isa指针,指向它的类,而每个类里面也有一个superclass指针,指向它的父类。
当执行[s run];首先通过s 对象的isa指针指到Student类,在类中寻找run方法,一旦找到就执行。
如果没有找到的话,就会通过superclass指针寻找父类中的run方法,知道找到为止,找不到的话程序会报错。
继承的使用场合
- 多个类有相同的属性和方法的时候,最好使用一个父类将公有属性和方法集中起来,便于子类的重用。子类继承这个父类就可以了
- 但是,大量使用继承会导致耦合性较高,类和类之间的依赖太强。必须要符合逻辑的依赖关系,才使用继承。
- 当B类完全拥有A类的属性和方法时,可以使B继承A
继承和组合的区别
下面看一段代码:
//// main.m// 继承1#import <Foundation/Foundation.h>//父类 People类,代表所有人类@interface People : NSObject- (void)run;@end@implementation People- (void)run{ NSLog(@"People在跑");}@end/***Score***/@interface Score : NSObject{ int value;}- (int)value;@end@implementation Score- (int)value{ return value;}@end//继承:xx是xxx//组合:xxx拥有xxx/****Student****/@interface Student : People{ //这里Student则是拥有的Score类里的所有属性和方法了 //组合 Score *_score;}- (void)run;@end@implementation Student- (void)run{ NSLog(@"Student在跑");}@endint main(int argc, const char * argv[]) { return 0;}
上面的代码显示,不使用继承也可以获取另一个类的所有方法和属性。这就是组合。从逻辑关系上score明显不适合被继承,Student又想拿到该类的所有内容,所以使用组合是不错的解决方法。
super关键字
//// main.m// 继承1#import <Foundation/Foundation.h>//父类 People类,代表所有人类@interface People : NSObject- (void)run;@end@implementation People- (void)run{ NSLog(@"People准备奔跑!!!");}@end/****Student****/@interface Student : People{}- (void)run;@end@implementation Student- (void)run{ [super run]; //直接调用父类的方法 NSLog(@"Student在跑");}@endint main(int argc, const char * argv[]) { Student *s=[Student new]; [s run]; return 0;}
输出结果:
People准备奔跑!!! Student在跑Program ended with exit code: 0
Super关键字可以使子类方法直接调用父类方法
Super不仅可以调用对象方法,还可以调用类方法
Super具体是调用类方法还是对象方法是看Supe所在环境
代码如下:
#import <Foundation/Foundation.h>//父类 People类,代表所有人类@interface People : NSObject- (void)run;+ (void)run;@end@implementation People- (void)run{ NSLog(@"-People准备奔跑!!!");}+ (void)run{ NSLog(@"+People准备奔跑!!!");}@end/****Student****/@interface Student : People{}- (void)run;+ (void)run;@end@implementation Student- (void)run{ [super run]; //直接调用父类的方法 NSLog(@"Student在跑");}+ (void)run{ [super run]; //直接调用父类的方法 NSLog(@"Student在跑");}@endint main(int argc, const char * argv[]) { [Student run]; return 0;}
3.多态
多态:字面指多种状态
父类指针指向子类对象
////#import <Foundation/Foundation.h>//父类 People类,代表所有人类@interface People : NSObject- (void)run;@end@implementation People- (void)run{ NSLog(@"People奔跑");}@end/****Student****/@interface Student : People{}- (void)run;@end@implementation Student- (void)run{ NSLog(@"Student奔跑");}@endint main(int argc, const char * argv[]) { //多态:父类指针指向子类对象 People *p = [Student new]; [p run]; return 0;}
输出结果为:
Student奔跑
为什么要用多态?
比如现在有个People类,还有两个子类Student ,Teacher继承这个People类
//父类 People类,代表所有人类@interface People : NSObject{ @public int age;}@end@implementation People@end/****Student****/@interface Student : People@end@implementation Student@end/****Teacher****/@interface Teacher : People@end@implementation Teacher@end
定义一个函数,用来对Student和Teacher的age赋值,由于它们是两个类,至少需要两个函数
void setAge1(Student *p){ p->age=20;}void setAge2(Teacher *p){ p->age=20;}
下面引入多态的概念,函数直接改成这样,使用一个函数就可以实现多个函数的功能,增加了重用
//如果函数的参数是一个父类类型,则可以传入父类,子类对象void setAge(People *p){ p->age=20;}int main(int argc, const char * argv[]) { //多态:父类指针指向子类对象 People *p = [Student new]; setAge(p); //这样就是设置Student的对象的age return 0;}
- OC从入门到精通-2.三大特性(封装,继承,多态)
- OC温故:类的三大特性(封装,继承,多态)
- OC温故:类的三大特性(封装,继承,多态)
- 黑马程序员--OC的三大特性 封装 继承 多态
- OC中的类的三大特性:继承,封装,多态
- OC语言-三大特性之封装继承多态
- OC-三大特征:封装、继承、多态
- java三大特性:封装、继承、多态
- java 三大特性 封装 继承 多态
- C++三大特性:封装、继承、多态
- Java三大特性,封装、继承、多态
- Java三大特性---封装,继承,多态
- C++三大特性:封装、继承、多态
- Java三大特性(封装,继承,多态)
- oc学习笔记(四)面向对象-类的三大特性:封装,继承,多态
- 黑马程序员——OC面向对象三大特性——封装,继承,多态。
- 黑马程序员——OC面向对象三大特性——封装,继承,多态。
- 黑马程序员——OC三大特性(继承、多态、封装)
- NSString转换成NSURL为空
- cordova打开远程网页等设置
- 剑指offer编程题目汇总(更新中。。)
- 深度解读海量数据存储和访问下的水平分库&去IOE
- [Java并发包学习七]解密ThreadLocal
- OC从入门到精通-2.三大特性(封装,继承,多态)
- hdu4763kmp
- hibernate,mybatis,beetlsql 全面比较
- 给tableview cell添加阴影:
- Android5.0 之 ToolBar基础功能
- html打开本地android app
- Android Audio 框架简读 <2>
- 在批处理模式下使用mysql
- 如何撰写创业计划书