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. 继承的基本用法
● 设计两个类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 : 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-吃东西----");
39 }
40 @end
41 
42 // 这个函数是专门用来喂动画
43 //void feed(Dog *d)
44 //{
45 //    [d eat];
46 //}
47 //
48 //void feed2(Cat *c)
49 //{
50 //    [c eat];
51 //}
52 //
53 
54 // 如果参数中使用的是父类类型,可以传入父类、子类对象
55 void feed(Animal *a)
56 {
57     [a eat];
58 }
59 
60 int main()
61 {
62     // 多态的局限性:父类类型的变量 不能 用来调用子类的方法
63     Animal *aa = [Animal new];
64      feed(aa);
65      
66      Dog *dd = [Dog new];
67      feed(dd);
68      
69      Cat *cc = [Cat new];
70      feed(cc);
71      
72     
73      // NSString *s = [Cat new];
74      Animal *c = [Cat new];
75      
76      
77      NSObject *n = [Dog new];
78      NSObject *n2 = [Animal new];
79     
80      
81       //多种形态
82      Dog *d = [Dog new]; // Dog类型
83     
84      //多态:父类指针指向子类对象
85      Animal *a = [Dog new];
86      
87      // 调用方法时会检测对象的真实形象
88      [a eat];
89     
90     return 0;
91 }
复制代码

 

3、 NSString的简单使用
 
1. 字符串的快速创建

NSStirng *str = @Hello;

2. 使用静态方法创建
3. 使用%@输出字符串

NSString *name = @mj;

NSLog(@我的名字是%@,  name);

 

复制代码
 1 #import <Foundation/Foundation.h>
 2 
 3 @interface Person : NSObject
 4 {
 5     //char *_name;
 6     NSString *_name;
 7 }
 8 @end
 9 
10 int main()
11 {
12     /*
13      // 最简单的创建字符串的方式
14      NSString *str = @"itcast";
15      
16      char *name = "itcast";
17      
18      
19      NSLog(@"我在%@上课", str);
20      //NSLog(@"%s", name);
21      */
22     
23     int age = 15;
24     int no = 5;
25     NSString *name = @"哈哈jack";
26     // length方法算的是字数
27     int size = [name length];
28     
29     NSLog(@"%d", size);
30     
31     // 创建OC字符串的另一种方式
32     NSString *newStr = [NSString stringWithFormat:@"My age is %d and no is %d and name is %@", age, no, name];
33     
34     
35     NSLog(@"---- %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 }
复制代码

 

 

posted @   巅峰之斗  阅读(1501)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示