黑马程序员——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 : NSObject
16 {
17     int _speed; // 速度
18 }
19
20 // 速度的getter和setter
21 - (void)setSpeed:(int)speed;
22 - (int)speed;
23
24 // 跟其他车子比较车速,返回速度差
25 - (int)compareSpeedWithOther:(Car *)car;
26 // 比较两辆车的车速,返回速度差
27 + (int)compareSpeedBetweenCar1:(Car *)car1 andCar2:(Car *)car2;
28 @end
29
30 @implementation Car
31 // 速度的getter和setter
32 - (void)setSpeed:(int)speed
33 {
34     _speed = speed;
35 }
36 - (int)speed
37 {
38     return _speed;
39 }
40
41 // 跟其他车子比较车速,返回速度差
42 - (int)compareSpeedWithOther:(Car *)car
43 {
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 *)car2
53 {
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 @end
22
23 @implementation Score
24 - (void)setCScore:(int)cScore
25 {
26     _cScore = cScore;
27
28     // 计算总分
29     _totalScore = _cScore + _ocScore;
30     _averageScoe = _totalScore/2;
31 }
32 - (int)cScore
33 {
34     return _cScore;
35 }
36
37 - (void)setOcScore:(int)ocScore
38 {
39     _ocScore = ocScore;
40
41     // 计算总分
42     _totalScore = _cScore + _ocScore;
43     _averageScoe = _totalScore/2;
44 }
45 // 监听成员变量的改变
46
47 - (int)ocScore
48 {
49     return _ocScore;
50 }
51
52 - (int)totalScore
53 {
54     return _totalScore;
55 }
56 - (int)averageScore
57 {
58     return _averageScoe;
59 }
60 @end
61
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. 继承的基本用法

● 设计两个类Bird、Dog

// 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 : NSObject
19 - (void)walk;
20
21 + (void)test;
22 - (void)test;
23
24 @end
25
26 @implementation Zoombie
27 - (void)walk
28 {
29     NSLog(@"往前挪两步******");
30 }
31
32 + (void)test
33 {
34     NSLog(@"Zoombie+test");
35 }
36
37 - (void)test
38 {
39     NSLog(@"Zoombie-test");
40 }
41 @end
42
43 // 跳跃僵尸
44 @interface JumpZoombie : Zoombie
45 + (void)haha;
46 - (void)haha2;
47 @end
48
49
50 @implementation JumpZoombie
51
52 + (void)haha
53 {
54     [super test];
55 }
56
57 - (void)haha2
58 {
59     [super test];
60 }
61
62 - (void)walk
63 {
64     // 跳两下
65     NSLog(@"跳两下");
66
67     // 走两下(直接调用父类的walk方法)
68     [super walk];
69     //NSLog(@"往前挪两步----");
70
71 }
72 @end
73
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> 基本上所有类的根类是NSObject
10  */
11
12
13 /********Animal的声明*******/
14 @interface Animal : NSObject
15 {
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 @end
26
27 /********Animal的实现*******/
28 @implementation Animal
29 - (void)setAge:(int)age
30 {
31     _age = age;
32 }
33 - (int)age
34 {
35     return _age;
36 }
37
38 - (void)setWeight:(double)weight
39 {
40     _weight = weight;
41 }
42 - (double)weight
43 {
44     return _weight;
45 }
46 @end
47
48 /********Dog*******/
49 // : Animal 继承了Animal,相当于拥有了Animal里面的所有成员变量和方法
50 // Animal称为Dog的父类
51 // Dog称为Animal的子类
52 @interface Dog : Animal
53 @end
54
55 @implementation Dog
56 @end
57
58 /********Cat*******/
59 @interface Cat : Animal
60 @end
61
62 @implementation Cat
63 @end
64
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 @end
13
14 // 狗
15 @interface Dog : Animal
16 - (void)run;
17 @end
18
19 @implementation  Dog
20 - (void)run
21 {
22     NSLog(@"Dog---跑起来");
23 }
24 - (void)eat
25 {
26     NSLog(@"Dog-吃东西----");
27 }
28 @end
29
30 // 猫
31 @interface Cat : Animal
32
33 @end
34
35 @implementation Cat
36 - (void)eat
37 {
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 : NSObject
100 {
101     double _radius; // 半径
102     Point2D *_point; // 圆心
103 }
104
105 // 半径的getter和setter
106 - (void)setRadius:(double)radius;
107 - (double)radius;
108
109 // 圆心的getter和setter
110 - (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 @end
120
121 @implementation Circle
122 // 半径的getter和setter
123 - (void)setRadius:(double)radius
124 {
125     _radius = radius;
126 }
127 - (double)radius
128 {
129     return _radius;
130 }
131
132 // 圆心的getter和setter
133 - (void)setPoint:(Point2D *)point
134 {
135     _point = point;
136 }
137 - (Point2D *)point
138 {
139     return _point;
140 }
141
142 // 跟其他圆是否重叠(重叠返回YES,否则返回NO)
143 - (BOOL)isInteractWithOther:(Circle *)other
144 {
145     return [Circle isInteractBetweenCircle1:self andCircle2:other];
146 }
147
148 // 判断两个圆是否重叠(重叠返回YES,否则返回NO)
149 + (BOOL)isInteractBetweenCircle1:(Circle *)circle1 andCircle2:(Circle *)circle2
150 {
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 @end
166
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 }
时间: 2024-08-04 01:08:42

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

黑马程序员-OC对象的三大特性

OC语言是面向对象的语言,其三大特性必不可少. 一.封装是一个很重要的概念,它避免外界直接访问或修改对象的属性,可以过滤不合理的值,让外界不必关心内部的细节.通过set方法来让外部设置成员的属性值,通过get方法来获得对象属性值. 1 #import <Foundation/Foundation.h> 2 @interface Student : NSObject</span></span> 3 { 4 int _age; //以下划线开头,避免和局部变量弄混 5 in

黑马程序员-OC面向对象继承关系和组合关系笔记

继承关系是描述类和类之间的关系,两个类分别称为子类和父类,子类继承了父类,子类就拥有了父类的属性和方法: 继承的关系特点描述出来就是:** "是" **  (例如:学生类 是 人类) 组合关系描述的语句是:**** "拥有" ***  (例如:学生有成绩这个属性,而成绩属性本来就是一个成绩类的对象 ) 继承示例代码: #import <Foundation/Foundation.h> //Animal类的声明 @interface Animal : NS

黑马程序员------OC面向对象之封装

---Android培训.iOS培训.Java培训,期待与您交流----- 一.面向对象和封装 面向对象三大特征:封装.继承.多态. 封装是对象和类概念的主要特性.它是隐藏内部实现,稳定外部接口,可以看作是"包装". 封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏. 好处:使用更加简单  变量更加安全 可以隐藏内部实现细节  开发速度加快. 苹果官方文档中,有一个配图生动的阐释了封装: @interface用于给人们显

黑马程序员------OC面向对象之继承

------Android培训.iOS培训.Java培训,期待与您交流----- 一.继承的基本概念 继承是面向的三大特征之一,指的是在一个类的基础上,定义一个新类:原本的类成为父类(基类),新类称为子类(派生类). 生活中,继承的例子也是数不胜数,比如一个儿子继承了他父亲,那么他就享受他父亲的财产了,当然不是全部,详细解释见下文. 再如,一个电器系列: 一层接着一层,电器为父类,下面的洗衣机.电脑.电视机都是电器的子类,下面的品牌名又是洗衣机.电脑.电视机的子类,当然也是电器的子类. 体现在代

黑马程序员-OC面向对象多态笔记

面向对象的多态是建立在继承上,可以说没有继承就没有多态: 多态:父类指针指向了子类的对象: 1 int main() 2 { 3 //假设已定义了Animal类和它的子类Dog,那么多态的代码体现就是 4 Animal *a = [Dog d];//父类指针指向了子类对象 5 6 } 多态的定义是比较简单的,也好理解,关键在于它的指针动态绑定,究竟调用哪个方法: 1 #import <Foundation/Foundation.h> 2 3 //Animal类的声明 4 @interface

黑马程序员------OC面向对象之多态

-----iOS培训.Android培训.Java培训,期待与您交流----- 一.多态的基本概念 多态(Polymorphism)按字面的意思就是"多种状态".在面向对象语言中,接口的多种不同的实现方式即为多态.引用Charlie Calverts对多态的描述--多态性是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作(摘自"Delphi4 编程技术内幕").简单的说,就是一句话:允许将

黑马程序员-OC学习笔记之Foundatio框架集合类

---------------------- IOS开发.Android培训.期待与您交流! ---------------------- 一.OC数组 OC数组是一个类,它也分不可变数组NSArray和可变数组NSMutableArray. 1?不可变数组的创建 // 创建一个不可变数组,元素为一个OC字符串对象 @"小桥" NSArray *array1 = [NSArray arrayWithObject:@"小桥"]; // 创建一个不可变数组,元素为多个O

【黑马程序员】————面向对象语法2

一.      set方法和get方法 1.          set方法和get方法的使用场合 @public的成员可以被随意赋值,应该使用set方法和get方法来管理成员的访问(类似机场的安检.水龙头过滤,过滤掉不合理的东西),比如僵尸的生命值不能为负数 成员变量尽量不要用@public 2.          set方法 1)       作用:提供一个方法给外界设置成员变量值,可以在方法里面对参数进行相应过滤 2)       命名规范: 1> 方法名必须以set开头 2> set后面

黑马程序员-OC self super isa指针

self指针: self是oc面向对象设计中的一个特殊指针,相当于java中的this,但是比this强大,this只能访问实例对象的相关方法和成员变量,或者说this只代表实例对象: self不仅可以代表实例对象,还可以代表类对象:谁调用当前方法,self就代表谁:如果self用在了以"-"号的方法中,也就是对象方法中,那么就代表实例对象,若果在"+"号开头的方法中,self就代表类对象,因为只有类对象才能调用以"+"号开头的方法: self调