首页 > 代码库 > 黑马程序员——OC面向对象的三大特性

黑马程序员——OC面向对象的三大特性

 
一、面向对象的三大特性:封装(成员变量)、继承和多态
1、 set方法和get方法
1. set方法和get方法的使用场合

@public的成员可以被随意赋值,应该使用set方法和get方法来管理成员的访问(类似机场的安检、水龙头过滤,过滤掉不合理的东西,比如僵尸的生命值不能为负数

2. set方法
1) 作用:用来设置成员变量,可以在方法里面过滤掉一些不合理的值
2) 命名规范:
方法都是以set开头,而且后面跟上成员变量名,成员变量名的首字母必须大写
形参名称不要跟成员变量同名
3. get方法
1) 作用:返回对象内部的成员变量
2) 命名规范:get方法的名称一般就跟成员变量同名
4. 成员变量的命名规范
成员变量都以下划线 _ 开头
可以跟get方法的名称区分开
可以跟其他局部变量区分开,一看到下划线开头的变量,肯定是成员变量
5. 代码示例

#import <Foundation/Foundation.h>

// 声明

@interface Car : NSObject

{

   int _wheels; // 轮子个数

}

/*set方法*/

- (void) setWheels:(int)wheels;

/*get方法*/

- (int) wheels;

@end

 

@implementation Car

// set方法的实现

- (void) setWheels:(int)wheels

{

   // 对外面传进来的轮子数进行过滤

   if (wheels<=0)

   {

       wheels = 1;

   }

   

   _wheels = wheels;

}

 

// get方法的实现

- (int) wheels

{

   return _wheels;

}

@end

6. 封装的好处
过滤不合理的值
屏蔽内部的赋值过程
让外界不必关注内部的细节
 
 1 /** 2  4.设计Car类 3  1> 属性 4  * 速度 5   6  2> 方法 7  * 属性相应的set和get方法 8  * 一个对象方法跟其他车子比较车速,返回速度差 9  * 一个类方法比较两辆车的车速,返回速度差10  */11 12 #import <Foundation/Foundation.h>13 14 //15 @interface Car : NSObject16 {17     int _speed; // 速度18 }19 20 // 速度的getter和setter21 - (void)setSpeed:(int)speed;22 - (int)speed;23 24 // 跟其他车子比较车速,返回速度差25 - (int)compareSpeedWithOther:(Car *)car;26 // 比较两辆车的车速,返回速度差27 + (int)compareSpeedBetweenCar1:(Car *)car1 andCar2:(Car *)car2;28 @end29 30 @implementation Car31 // 速度的getter和setter32 - (void)setSpeed:(int)speed33 {34     _speed = speed;35 }36 - (int)speed37 {38     return _speed;39 }40 41 // 跟其他车子比较车速,返回速度差42 - (int)compareSpeedWithOther:(Car *)car43 {44     // 第1种思路45     // return _speed - [car speed];46     47     // 第2种思路48     return [Car compareSpeedBetweenCar1:self andCar2:car];49 }50 51 // 比较两辆车的车速,返回速度差52 + (int)compareSpeedBetweenCar1:(Car *)car1 andCar2:(Car *)car253 {54     return [car1 speed] - [car2 speed];55 }56 @end

 

2、 类方法
1. 基本概念

直接可以用类名来执行的方法类本身会在内存中占据存储空间,里面有类\对象方法列表

2. 类方法和对象方法对比
1) 对象方法
以减号-开头
只能让对象调用,没有对象,这个方法根本不可能被执行
对象方法能访问实例变量(成员变量)

 

2) 方法
以加号+开头
只能用类名调用,对象不能调用
类方法中不能访问实例变量(成员变量)
使用场合:当不需要访问成员变量的时候,尽量用类方法
3) 类方法和对象方法可以同名
 
3、 self关键字
1. 成员变量和局部变量同名
当成员变量和局部变量同名时,采取就近原则,访问的是局部变量
self访问成员变量,区分同名的局部变量
2. 使用细节
1) 出现的地方:所有的OC方法中(对象方法\类方法),不能出现在函数
2) 作用
使用 "self->成员变量名访问当前方法调用的成员变量
使用 "[self 方法名];" 来调用方法(对象方法\类方法)
3. 常见错误
低级错误:用self去调用函数
类方法中self调用对象方法,对象方法中用self调用类方法
self死循环
 

练习:设计一个成绩类

 * C语言成绩(可读可写)

 * OC成绩(可读可写)

 * 总分(只读)

 * 平均分(只读)

 1 #import <Foundation/Foundation.h> 2  3 @interface Score : NSObject 4 { 5     int _cScore; // C语言成绩 6     int _ocScore; // OC成绩 7      8     int _totalScore;// 总分 9     int _averageScoe; // 平均分10 }11 12 - (void)setCScore:(int)cScore;13 - (int)cScore;14 15 - (void)setOcScore:(int)ocScore;16 - (int)ocScore;17 18 - (int)totalScore;19 - (int)averageScore;20 21 @end22 23 @implementation Score24 - (void)setCScore:(int)cScore25 {26     _cScore = cScore;27     28     // 计算总分29     _totalScore = _cScore + _ocScore;30     _averageScoe = _totalScore/2;31 }32 - (int)cScore33 {34     return _cScore;35 }36 37 - (void)setOcScore:(int)ocScore38 {39     _ocScore = ocScore;40     41     // 计算总分42     _totalScore = _cScore + _ocScore;43     _averageScoe = _totalScore/2;44 }45 // 监听成员变量的改变46 47 - (int)ocScore48 {49     return _ocScore;50 }51 52 - (int)totalScore53 {54     return _totalScore;55 }56 - (int)averageScore57 {58     return _averageScoe;59 }60 @end61 62 63 int main()64 {65     Score *s = [Score new];66     67     [s setCScore:90];68     [s setOcScore:100];69     70     [s setCScore:80];71     72     73     int a = [s totalScore];74     75     NSLog(@"总分:%d", a);76     

 

二、 继承
1. 继承的基本用法
● 设计两个类BirdDog

// Bird的声明

@interface Bird : NSObject

{

   @public

   int weight;

}

- (void)eat;

@end

// Bird定义

@implementation Bird

- (void)eat {

   NSLog(@"吃吃吃-体重:%d", weight);

}

@end

// Dog声明

@interface Dog : NSObject

{

   @public

   int weight;

}

- (void)eat;

@end

// Dog的定义

@implementation Dog

- (void)eat {

   NSLog(@"吃吃吃-体重:%d", weight);

}

@end

● 有相同的属性和行为,抽出一个父类Animal(先抽取weight属性,再抽取eat方法)

// Animal的声明

@interface Animal : NSObject

{

   @public

       int weight;

}

- (void)eat;

@end

// Animal的定义

@implementation Animal

- (void)eat {

   NSLog(@"吃吃吃-体重:%d", weight);

}

@end

● 子类在父类的基础上拓充属性和方法

// Bird的声明

@interface Bird : Animal

{

   @public

       int height;

}

- (void)fly;

@end

 

// Bird的定义

@implementation Bird

- (void)fly {

   NSLog(@"飞飞飞-高度:%d", height);

}

@end

 

// Dog的声明

@interface Dog : Animal

{

   @public

       int speed;

}

- (void)run;

@end

// Dog的定义

@implementation Dog

- (void)run {

   NSLog(@"跑跑跑-高度:%d", speed);

}

@end

● 子类方法和属性的访问过程:如果子类没有,就去访问父类的
● 父类被继承了还是能照常使用的
● 父类的静态方法
● 画继承结构图,从子类抽取到父类
● NSObject的引出:全部OC类的最终父类,包含了一些常用方法,比如+new

 

2. 继承的专业术语
● 父类\超类  superclass
● 子类  subclass\subclasses

 

3. 继承的细节
● 单继承
● 子类和父类不能有相同的成员变量
● 方法的重写

 

4. super关键字
● 分别调用父类的对象方法和类方法

   在子类中重写方法时,可以让调用者跳过这一层而调用父类中的方法。

 

 1 /* 2  僵尸 3   4  跳跃僵尸、舞王僵尸、铁桶僵尸 5  */ 6 #import <Foundation/Foundation.h> 7  8 /* 9  super的作用10  1.直接调用父类中的某个方法11  2.super处在对象方法中,那么就会调用父类的对象方法12  super处在类方法中,那么就会调用父类的类方法13  14  3.使用场合:子类重写父类的方法时想保留父类的一些行为15  */16 17 // 僵尸18 @interface Zoombie : NSObject19 - (void)walk;20 21 + (void)test;22 - (void)test;23 24 @end25 26 @implementation Zoombie27 - (void)walk28 {29     NSLog(@"往前挪两步******");30 }31 32 + (void)test33 {34     NSLog(@"Zoombie+test");35 }36 37 - (void)test38 {39     NSLog(@"Zoombie-test");40 }41 @end42 43 // 跳跃僵尸44 @interface JumpZoombie : Zoombie45 + (void)haha;46 - (void)haha2;47 @end48 49 50 @implementation JumpZoombie51 52 + (void)haha53 {54     [super test];55 }56 57 - (void)haha258 {59     [super test];60 }61 62 - (void)walk63 {64     // 跳两下65     NSLog(@"跳两下");66     67     // 走两下(直接调用父类的walk方法)68     [super walk];69     //NSLog(@"往前挪两步----");70     71 }72 @end73 74 int main()75 {76     //[JumpZoombie haha];77     JumpZoombie *jz = [JumpZoombie new];78     79     [jz walk];80     81     return 0;82 }

 

 5. 继承的好处

● 不改变原来模型的基础上,拓充方法
● 建立了类与类之间的联系
● 抽取了公共代码
● 坏处:耦合性强

 

6. 继承的使用场合
● 它的所有属性都是你想要的,一般就继承
● 它的部分属性是你想要的,可以抽取出另一个父类
继承的使用场合练习

 1> 当两个类拥有相同属性和方法的时候,就可以将相同的东西抽取到一个父类中

 2> 当A类完全拥有B类中的部分属性和方法时,可以考虑让B类继承A类

 A

 {

    int _age;

    int _no;

 }

 

 B : A

 {

    int _weight;

 }

 

 // 继承:xx 是 xxx

 // 组合:xxx 拥有 xxx

 

 2.组合

 A

 {

     int _age;

     int _no;

 }

 

 B

 {

     A *_a;

     int _weight;

 }

 

 
 1 #import <Foundation/Foundation.h> 2 /* 3  1.继承的好处: 4  1> 抽取重复代码 5  2> 建立了类之间的关系 6  3> 子类可以拥有父类中的所有成员变量和方法 7   8  2.注意点 9  1> 基本上所有类的根类是NSObject10  */11 12 13 /********Animal的声明*******/14 @interface Animal : NSObject15 {16     int _age;17     double _weight;18 }19 20 - (void)setAge:(int)age;21 - (int)age;22 23 - (void)setWeight:(double)weight;24 - (double)weight;25 @end26 27 /********Animal的实现*******/28 @implementation Animal29 - (void)setAge:(int)age30 {31     _age = age;32 }33 - (int)age34 {35     return _age;36 }37 38 - (void)setWeight:(double)weight39 {40     _weight = weight;41 }42 - (double)weight43 {44     return _weight;45 }46 @end47 48 /********Dog*******/49 // : Animal 继承了Animal,相当于拥有了Animal里面的所有成员变量和方法50 // Animal称为Dog的父类51 // Dog称为Animal的子类52 @interface Dog : Animal53 @end54 55 @implementation Dog56 @end57 58 /********Cat*******/59 @interface Cat : Animal60 @end61 62 @implementation Cat63 @end64 65 int main()66 {67     Dog *d = [Dog new];68     69     [d setAge:10];70     71     NSLog(@"age=%d", [d age]);72     return 0;73 }

 

 

三、多态
 
1. 多态的基本概念
● 某一类事物的多种形态,必须要有继承,没有继承就没有多态。
● OC对象具有多态性,多态在代码中的体现即父类指针指向子类对象。

 

2. 多态的体现

Person *p = [Student new];

p->age = 100;

[p walk];

● 子类对象赋值给父类指针
● 父类指针访问对应的属性和方法

 

3. 多态的好处
● 用父类接收参数,节省代码

 

4. 多态的局限性
● 不能访问子类的属性(可以考虑强制转换)

 

5. 多态的细节
● 动态绑定:在运行时根据对象的类型确定动态调用的方法
 

多态使用总结

 1.没有继承就没有多态

 2.代码的体现:父类类型的指针指向子类对象

 3.好处:如果函数\方法参数中使用的是父类类型,可以传入父类、子类对象

 4.局限性: 父类类型的变量不能直接调用子类特有的方法。必须强转为子类类型变量后,才能直接调用子类特有的方法

 

 1 #import <Foundation/Foundation.h> 2 // 动物 3 @interface Animal : NSObject 4 - (void)eat; 5 @end 6  7 @implementation Animal 8 - (void)eat 9 {10     NSLog(@"Animal-吃东西----");11 }12 @end13 14 //15 @interface Dog : Animal16 - (void)run;17 @end18 19 @implementation  Dog20 - (void)run21 {22     NSLog(@"Dog---跑起来");23 }24 - (void)eat25 {26     NSLog(@"Dog-吃东西----");27 }28 @end29 30 //31 @interface Cat : Animal32 33 @end34 35 @implementation Cat36 - (void)eat37 {38     NSLog(@"Cat-吃东西 %ld", [newStr length]);36     37     return 0;38 }

作业

  1 /**  2  6.设计一个类Circle,用来表示二维平面中的圆  3  1> 属性  4  * double radius (半径)  5  * Point2D *point (圆心)  6    7  2> 方法  8  * 属性相应的set和get方法  9  * 设计一个对象方法判断跟其他圆是否相交(重叠返回YES,否则返回NO) 10  * 设计一个类方法判断两个圆是否相交(重叠返回YES,否则返回NO) 11  */ 12 #import <Foundation/Foundation.h> 13 #import <math.h> 14  15 // 16 @interface Point2D : NSObject 17 { 18     double _x; // x值 19     double _y; // y值 20 } 21 // x值的getter和setter 22 - (void)setX:(double)x; 23 - (double)x; 24  25 // y值的getter和setter 26 - (void)setY:(double)y; 27 - (double)y; 28  29 // 同时设置x和y 30 - (void)setX:(double)x andY:(double)y; 31  32 // 计算跟其他点的距离 33 - (double)distanceWithOther:(Point2D *)other; 34  35 // 计算两个点之间的距离 36 + (double)distanceBetweenPoint1:(Point2D *)p1 andPoint2:(Point2D *)p2; 37 @end 38  39 @implementation Point2D 40 // x值的getter和setter 41 - (void)setX:(double)x 42 { 43     _x = x; 44 } 45 - (double)x 46 { 47     return _x; 48 } 49  50 // y值的getter和setter 51 - (void)setY:(double)y 52 { 53     _y = y; 54 } 55 - (double)y 56 { 57     return _y; 58 } 59  60 // 同时设置x和y 61 - (void)setX:(double)x andY:(double)y 62 { 63     // 第1种思路 64     // _x = x; 65     // _y = y; 66      67     // 第2种思路 68     [self setX:x]; 69     [self setY:y]; 70 } 71  72 // 计算跟其他点的距离 73 - (double)distanceWithOther:(Point2D *)other 74 { 75     // 不要再傻乎乎算一遍了,直接调用类方法即可 76     return [Point2D distanceBetweenPoint1:self andPoint2:other]; 77 } 78  79 // 计算两个点之间的距离 80 + (double)distanceBetweenPoint1:(Point2D *)p1 andPoint2:(Point2D *)p2 81 { 82     // 两点距离公式:( (x1-x2)的平方 + (y1-y2)的平方 )开根 83      84     // x1-x2 85     double xDelta = [p1 x] - [p2 x]; 86     // (x1-x2)的平方 87     double xDeltaPingFang = pow(xDelta, 2); 88      89     // y1-y2 90     double yDelta = [p1 y] - [p2 y]; 91     // (y1-y2)的平方 92     double yDeltaPingFang = pow(yDelta, 2); 93      94     return sqrt(xDeltaPingFang + yDeltaPingFang); 95 } 96 @end 97  98 // 99 @interface Circle : NSObject100 {101     double _radius; // 半径102     Point2D *_point; // 圆心103 }104 105 // 半径的getter和setter106 - (void)setRadius:(double)radius;107 - (double)radius;108 109 // 圆心的getter和setter110 - (void)setPoint:(Point2D *)point;111 - (Point2D *)point;112 113 114 // 跟其他圆是否重叠(重叠返回YES,否则返回NO)115 - (BOOL)isInteractWithOther:(Circle *)other;116 // 判断两个圆是否重叠(重叠返回YES,否则返回NO)117 + (BOOL)isInteractBetweenCircle1:(Circle *)circle1 andCircle2:(Circle *)circle2;118 119 @end120 121 @implementation Circle122 // 半径的getter和setter123 - (void)setRadius:(double)radius124 {125     _radius = radius;126 }127 - (double)radius128 {129     return _radius;130 }131 132 // 圆心的getter和setter133 - (void)setPoint:(Point2D *)point134 {135     _point = point;136 }137 - (Point2D *)point138 {139     return _point;140 }141 142 // 跟其他圆是否重叠(重叠返回YES,否则返回NO)143 - (BOOL)isInteractWithOther:(Circle *)other144 {145     return [Circle isInteractBetweenCircle1:self andCircle2:other];146 }147 148 // 判断两个圆是否重叠(重叠返回YES,否则返回NO)149 + (BOOL)isInteractBetweenCircle1:(Circle *)circle1 andCircle2:(Circle *)circle2150 {151     // 如果两个圆心的距离 >= 两个圆的半径和,就不重叠152     // 如果两个圆心的距离 < 两个圆的半径和,就重叠153     154     // 两个圆心155     Point2D *point1 = [circle1 point];156     Point2D *point2 = [circle2 point];157     // 两个圆心的距离158     double distance = [point1 distanceWithOther:point2];159     160     // 半径和161     double radiusSum = [circle1 radius] + [circle2 radius];162     163     return distance < radiusSum;164 }165 @end166 167 int main()168 {169     Circle *c1 = [Circle new];170     // 设置半径171     [c1 setRadius:2];172     // 设置圆心173     Point2D *p1 = [Point2D new];174     [p1 setX:10 andY:10];175     [c1 setPoint:p1];176     177     Circle *c2 = [Circle new];178     // 设置半径179     [c2 setRadius:2];180     // 设置圆心181     Point2D *p2 = [Point2D new];182     [p2 setX:13 andY:14];183     [c2 setPoint:p2];184     185     // 圆心距离是5  半径和是4  所以不重叠186     BOOL b1 = [c1 isInteractWithOther:c2];187     188     BOOL b2 = [Circle isInteractBetweenCircle1:c1 andCircle2:c2];189     190     NSLog(@"%d %d", b1, b2);191     192     return 0;193 }

 

 

黑马程序员——OC面向对象的三大特性