您的位置:首页 > 其它

OC面向对象的三大特性

2014-12-12 13:43 176 查看
一、面向对象的三大特性:封装(成员变量)、继承和多态
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. 封装的好处
➢ 过滤不合理的值
➢ 屏蔽内部的赋值过程
➢ 让外界不必关注内部的细节

/**
4.设计Car类
1> 属性
* 速度

2> 方法
* 属性相应的set和get方法
* 一个对象方法跟其他车子比较车速,返回速度差
* 一个类方法比较两辆车的车速,返回速度差
*/

#import <Foundation/Foundation.h>

// 车
@interface Car : NSObject
{
int _speed; // 速度
}

// 速度的getter和setter
- (void)setSpeed:(int)speed;
- (int)speed;

// 跟其他车子比较车速,返回速度差
- (int)compareSpeedWithOther:(Car *)car;
// 比较两辆车的车速,返回速度差
+ (int)compareSpeedBetweenCar1:(Car *)car1 andCar2:(Car *)car2;
@end

@implementation Car
// 速度的getter和setter
- (void)setSpeed:(int)speed
{
_speed = speed;
}
- (int)speed
{
return _speed;
}

// 跟其他车子比较车速,返回速度差
- (int)compareSpeedWithOther:(Car *)car
{
// 第1种思路
// return _speed - [car speed];

// 第2种思路
return [Car compareSpeedBetweenCar1:self andCar2:car];
}

// 比较两辆车的车速,返回速度差
+ (int)compareSpeedBetweenCar1:(Car *)car1 andCar2:(Car *)car2
{
return [car1 speed] - [car2 speed];
}
@end


2、 类方法
1. 基本概念
直接可以用类名来执行的方法(类本身会在内存中占据存储空间,里面有类\对象方法列表)

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

2) 类方法
➢ 以加号+开头
➢ 只能用类名调用,对象不能调用
➢ 类方法中不能访问实例变量(成员变量)
➢ 使用场合:当不需要访问成员变量的时候,尽量用类方法
3) 类方法和对象方法可以同名

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

练习:设计一个成绩类

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

* OC成绩(可读可写)

* 总分(只读)

* 平均分(只读)

#import <Foundation/Foundation.h>

@interface Score : NSObject
{
int _cScore; // C语言成绩
int _ocScore; // OC成绩

int _totalScore;// 总分
int _averageScoe; // 平均分
}

- (void)setCScore:(int)cScore;
- (int)cScore;

- (void)setOcScore:(int)ocScore;
- (int)ocScore;

- (int)totalScore;
- (int)averageScore;

@end

@implementation Score
- (void)setCScore:(int)cScore
{
_cScore = cScore;

// 计算总分
_totalScore = _cScore + _ocScore;
_averageScoe = _totalScore/2;
}
- (int)cScore
{
return _cScore;
}

- (void)setOcScore:(int)ocScore
{
_ocScore = ocScore;

// 计算总分
_totalScore = _cScore + _ocScore;
_averageScoe = _totalScore/2;
}
// 监听成员变量的改变

- (int)ocScore
{
return _ocScore;
}

- (int)totalScore
{
return _totalScore;
}
- (int)averageScore
{
return _averageScoe;
}
@end

int main()
{
Score *s = [Score new];

[s setCScore:90];
[s setOcScore:100];

[s setCScore:80];

int a = [s totalScore];

NSLog(@"总分:%d", a);


二、 继承
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关键字
● 分别调用父类的对象方法和类方法
在子类中重写方法时,可以让调用者跳过这一层而调用父类中的方法。

/*
僵尸

跳跃僵尸、舞王僵尸、铁桶僵尸
*/
#import <Foundation/Foundation.h>

/*
super的作用
1.直接调用父类中的某个方法
2.super处在对象方法中,那么就会调用父类的对象方法
super处在类方法中,那么就会调用父类的类方法

3.使用场合:子类重写父类的方法时想保留父类的一些行为
*/

// 僵尸
@interface Zoombie : NSObject
- (void)walk;

+ (void)test;
- (void)test;

@end

@implementation Zoombie
- (void)walk
{
NSLog(@"往前挪两步******");
}

+ (void)test
{
NSLog(@"Zoombie+test");
}

- (void)test
{
NSLog(@"Zoombie-test");
}
@end

// 跳跃僵尸
@interface JumpZoombie : Zoombie
+ (void)haha;
- (void)haha2;
@end

@implementation JumpZoombie

+ (void)haha
{
[super test];
}

- (void)haha2
{
[super test];
}

- (void)walk
{
// 跳两下
NSLog(@"跳两下");

// 走两下(直接调用父类的walk方法)
[super walk];
//NSLog(@"往前挪两步----");

}
@end

int main()
{
//[JumpZoombie haha];
JumpZoombie *jz = [JumpZoombie new];

[jz walk];

return 0;
}


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;

}

#import <Foundation/Foundation.h>
/*
1.继承的好处:
1> 抽取重复代码
2> 建立了类之间的关系
3> 子类可以拥有父类中的所有成员变量和方法

2.注意点
1> 基本上所有类的根类是NSObject
*/

/********Animal的声明*******/
@interface Animal : NSObject
{
int _age;
double _weight;
}

- (void)setAge:(int)age;
- (int)age;

- (void)setWeight:(double)weight;
- (double)weight;
@end

/********Animal的实现*******/
@implementation Animal
- (void)setAge:(int)age
{
_age = age;
}
- (int)age
{
return _age;
}

- (void)setWeight:(double)weight
{
_weight = weight;
}
- (double)weight
{
return _weight;
}
@end

/********Dog*******/
// : Animal 继承了Animal,相当于拥有了Animal里面的所有成员变量和方法
// Animal称为Dog的父类
// Dog称为Animal的子类
@interface Dog : Animal
@end

@implementation Dog
@end

/********Cat*******/
@interface Cat : Animal
@end

@implementation Cat
@end

int main()
{
Dog *d = [Dog new];

[d setAge:10];

NSLog(@"age=%d", [d age]);
return 0;
}


三、多态

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

2. 多态的体现
Person *p = [Student new];

p->age = 100;

[p walk];

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

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

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

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

[b]多态使用总结[/b]

1.没有继承就没有多态

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

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

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

#import <Foundation/Foundation.h>
// 动物
@interface Animal : NSObject
- (void)eat;
@end

@implementation Animal
- (void)eat
{
NSLog(@"Animal-吃东西----");
}
@end

// 狗
@interface Dog : Animal
- (void)run;
@end

@implementation  Dog
- (void)run
{
NSLog(@"Dog---跑起来");
}
- (void)eat
{
NSLog(@"Dog-吃东西----");
}
@end

// 猫
@interface Cat : Animal

@end

@implementation Cat
- (void)eat
{
NSLog(@"Cat-吃东西----");
}
@end

// 这个函数是专门用来喂动画
//void feed(Dog *d)
//{
//    [d eat];
//}
//
//void feed2(Cat *c)
//{
//    [c eat];
//}
//

// 如果参数中使用的是父类类型,可以传入父类、子类对象
void feed(Animal *a)
{
[a eat];
}

int main()
{
// 多态的局限性:父类类型的变量 不能 用来调用子类的方法
Animal *aa = [Animal new];
feed(aa);

Dog *dd = [Dog new];
feed(dd);

Cat *cc = [Cat new];
feed(cc);

// NSString *s = [Cat new];
Animal *c = [Cat new];

NSObject *n = [Dog new];
NSObject *n2 = [Animal new];

//多种形态
Dog *d = [Dog new]; // Dog类型

//多态:父类指针指向子类对象
Animal *a = [Dog new];

// 调用方法时会检测对象的真实形象
[a eat];

return 0;
}


3、 NSString的简单使用

1. 字符串的快速创建
NSStirng *str = @“Hello”;

2. 使用静态方法创建
3. 使用%@输出字符串
NSString *name = @”mj”;

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

#import <Foundation/Foundation.h>

@interface Person : NSObject
{
//char *_name;
NSString *_name;
}
@end

int main()
{
/*
// 最简单的创建字符串的方式
NSString *str = @"itcast";

char *name = "itcast";

NSLog(@"我在%@上课", str);
//NSLog(@"%s", name);
*/

int age = 15;
int no = 5;
NSString *name = @"哈哈jack";
// length方法算的是字数
int size = [name length];

NSLog(@"%d", size);

// 创建OC字符串的另一种方式
NSString *newStr = [NSString stringWithFormat:@"My age is %d and no is %d and name is %@", age, no, name];

NSLog(@"---- %ld", [newStr length]);

return 0;
}


作业

/**
6.设计一个类Circle,用来表示二维平面中的圆
1> 属性
* double radius (半径)
* Point2D *point (圆心)

2> 方法
* 属性相应的set和get方法
* 设计一个对象方法判断跟其他圆是否相交(重叠返回YES,否则返回NO)
* 设计一个类方法判断两个圆是否相交(重叠返回YES,否则返回NO)
*/
#import <Foundation/Foundation.h>
#import <math.h>

// 点
@interface Point2D : NSObject
{
double _x; // x值
double _y; // y值
}
// x值的getter和setter
- (void)setX:(double)x;
- (double)x;

// y值的getter和setter
- (void)setY:(double)y;
- (double)y;

// 同时设置x和y
- (void)setX:(double)x andY:(double)y;

// 计算跟其他点的距离
- (double)distanceWithOther:(Point2D *)other;

// 计算两个点之间的距离
+ (double)distanceBetweenPoint1:(Point2D *)p1 andPoint2:(Point2D *)p2;
@end

@implementation Point2D
// x值的getter和setter
- (void)setX:(double)x
{
_x = x;
}
- (double)x
{
return _x;
}

// y值的getter和setter
- (void)setY:(double)y
{
_y = y;
}
- (double)y
{
return _y;
}

// 同时设置x和y
- (void)setX:(double)x andY:(double)y
{
// 第1种思路
// _x = x;
// _y = y;

// 第2种思路
[self setX:x];
[self setY:y];
}

// 计算跟其他点的距离
- (double)distanceWithOther:(Point2D *)other
{
// 不要再傻乎乎算一遍了,直接调用类方法即可
return [Point2D distanceBetweenPoint1:self andPoint2:other];
}

// 计算两个点之间的距离
+ (double)distanceBetweenPoint1:(Point2D *)p1 andPoint2:(Point2D *)p2
{
// 两点距离公式:( (x1-x2)的平方 + (y1-y2)的平方 )开根

// x1-x2
double xDelta = [p1 x] - [p2 x];
// (x1-x2)的平方
double xDeltaPingFang = pow(xDelta, 2);

// y1-y2
double yDelta = [p1 y] - [p2 y];
// (y1-y2)的平方
double yDeltaPingFang = pow(yDelta, 2);

return sqrt(xDeltaPingFang + yDeltaPingFang);
}
@end

// 圆
@interface Circle : NSObject
{
double _radius; // 半径
Point2D *_point; // 圆心
}

// 半径的getter和setter
- (void)setRadius:(double)radius;
- (double)radius;

// 圆心的getter和setter
- (void)setPoint:(Point2D *)point;
- (Point2D *)point;

// 跟其他圆是否重叠(重叠返回YES,否则返回NO)
- (BOOL)isInteractWithOther:(Circle *)other;
// 判断两个圆是否重叠(重叠返回YES,否则返回NO)
+ (BOOL)isInteractBetweenCircle1:(Circle *)circle1 andCircle2:(Circle *)circle2;

@end

@implementation Circle
// 半径的getter和setter
- (void)setRadius:(double)radius
{
_radius = radius;
}
- (double)radius
{
return _radius;
}

// 圆心的getter和setter
- (void)setPoint:(Point2D *)point
{
_point = point;
}
- (Point2D *)point
{
return _point;
}

// 跟其他圆是否重叠(重叠返回YES,否则返回NO)
- (BOOL)isInteractWithOther:(Circle *)other
{
return [Circle isInteractBetweenCircle1:self andCircle2:other];
}

// 判断两个圆是否重叠(重叠返回YES,否则返回NO)
+ (BOOL)isInteractBetweenCircle1:(Circle *)circle1 andCircle2:(Circle *)circle2
{
// 如果两个圆心的距离 >= 两个圆的半径和,就不重叠
// 如果两个圆心的距离 < 两个圆的半径和,就重叠

// 两个圆心
Point2D *point1 = [circle1 point];
Point2D *point2 = [circle2 point];
// 两个圆心的距离
double distance = [point1 distanceWithOther:point2];

// 半径和
double radiusSum = [circle1 radius] + [circle2 radius];

return distance < radiusSum;
}
@end

int main()
{
Circle *c1 = [Circle new];
// 设置半径
[c1 setRadius:2];
// 设置圆心
Point2D *p1 = [Point2D new];
[p1 setX:10 andY:10];
[c1 setPoint:p1];

Circle *c2 = [Circle new];
// 设置半径
[c2 setRadius:2];
// 设置圆心
Point2D *p2 = [Point2D new];
[p2 setX:13 andY:14];
[c2 setPoint:p2];

// 圆心距离是5  半径和是4  所以不重叠
BOOL b1 = [c1 isInteractWithOther:c2];

BOOL b2 = [Circle isInteractBetweenCircle1:c1 andCircle2:c2];

NSLog(@"%d %d", b1, b2);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: