IOS开发学习笔记010-面向对象的三大特性

面向对象的三大特性

  1、封装

  2、继承

  3、多态

一、封装

将类内部的属性保护起来,在外部不能直接访问,那么如果需要访问怎么办呢?

OC提供了set方法来对成员变量进行访问

set方法

1、作用:提供一个方法给外界设置age属性的值

2、命名规范

  方法名必须是set开头

  set后面跟上成员变量的名称,成员变量首字母必须大写

  返回值一定是void

  一定要接收一个参数,并且和成员变量类型一致

   形参名不能和成员变量名一样

声明

- (void)setAge:(int)newAge;//声明

实现

 - (void)setAge:(int)newAge//set方法实现
{
if(newAge <= )//如果小于0岁就赋值为1
{
newAge = ;
}
age = newAge;//设置年龄
}

使用

  Student *p = [Student new];//新建对象
[p setAge:];//设置属性
[p study];//调用方法

get方法

1、作用:返回对象内部的成员变量

2、命名规范:

肯定有返回值,返回类型和成员变量一致

方法名和成员变量名一样

不需要接收参数

声明

- (int)age;//

实现

 - (int)age//
{
return age;
}

使用

  NSLog(@"%d岁的学生在学习!",[p age]);

成员变量的使用

命名规范:

  成员变量都以下划线 _ 开头

  可以跟get方法的名称区分开

  可以跟其他局部变量区分开,一看到下划线开头的变量,肯定是成员变量

 @interface Student : NSObject
{
//@public
//成员变量
//让成员变量和get方法区分开,成员变量都要加_
int _no;
int _age;
Sex _sex;
} @end

练习1

 #import <Foundation/Foundation.h>

 //成绩类
/*
C成绩(读写)
OC成绩(读写)
平均分(只读)
总分(只读)
*/
//类的声明
@interface Score : NSObject
{
int _cScore;//c成绩
int _ocScore;//oc成绩 int _totalScore;//总分
int _averageScore;//平均分
} //方法声明
//set
- (void)setCScore:(int)newCScore;
- (void)setOcScore:(int)newOcScore; //get
- (int)cScore;
- (int)ocScore;
- (int)totalScore;
- (int)averageScore; @end //类的实现
@implementation Score
//方法实现
- (void)setCScore:(int)newCScore
{
_cScore = newCScore;
//计算总分和平均分
_totalScore = _cScore + _ocScore;
_averageScore = _totalScore/;
}
- (void)setOcScore:(int)newOcScore
{
_ocScore = newOcScore;
//计算总分和平均分
_totalScore = _cScore + _ocScore;
_averageScore = _totalScore/;
} - (int)cScore
{
return _cScore;
}
- (int)ocScore
{
return _ocScore;
}
- (int)totalScore
{
return _totalScore;
}
- (int)averageScore
{
return _averageScore;
}
@end int main()
{
Score *p = [Score new];//新建对象
[p setCScore:];//set方法
[p setOcScore:];//set方法 NSLog(@"总分:%d",[p totalScore]); NSLog(@"平均分:%d",[p averageScore]); return ;
}

OC弱语法

如果调用不存在的方法,那么在编译和链接时都不会报错,最多有一个警告。只有在运行时才回出错。

unrecognized selector sent to instance 0x0000034034C0

给对象发送的消息不能识别

OC只有在运行过程中才会检测对象有没有实现相应的方法。

类方法

1、以+开头

2、通过类名调用的方法。

3、类方法不能访问成员变量

4、类方法和对象方法可以重名

5、使用场合:当不需要访问成员变量时尽量用类方法

声明

+ (void)printClassName;//

实现

 + (void)printClassName//
{
NSLog(@"class name is Person");
}

使用

 [Person printClassName];//类方法的调用,直接使用类名

工具类

没有成员变量的类,里面的方法全是类方法。

示例

 #import <Foundation/Foundation.h>
/*
工具类
没有成员变量
所有方法全是类方法
*/
//类声明
@interface JiSuanQi : NSObject + (void)printClassName;//类方法 + (int)sumOfSum1:(int)sum1 andSum2:(int)sum2;//类方法 @end
//类的实现
@implementation JiSuanQi
+ (void)printClassName
{
NSLog(@"class name is JiSuanQi"); }
+ (int)sumOfSum1:(int)sum1 andSum2:(int)sum2
{
return sum1 + sum2;
} @end int main()
{ [JiSuanQi printClassName];//类方法的调用,直接使用类名
int res = [JiSuanQi sumOfSum1: andSum2:];
NSLog(@"%d",res);
return ;
}

self关键字

谁调用,self代表谁。

如果用对象调用,就代表对象,如果是类调用,就代表类。

成员变量和局部变量同名

  当成员变量和局部变量同名时,采取就近原则,访问的是局部变量

  用self访问成员变量,区分同名的局部变量

self出现的位置:

  所有的OC方法中(对象方法\类方法),不能出现在函数

作用方式:

  使用 "self->成员变量名" 访问当前方法调用的成员变量

  使用 "[self 方法名];" 来调用方法(对象方法\类方法)

 - (void)setAge:(int)newAge
{
_age = newAge; int _age = ;//局部变量与成员变量同名时,如果需要使用成员变量,则需要使用self关键字
NSLog(@"age is %d",self->_age);//self 是一个指指针,指向调用的对象
}

 小练习

  设计Car类,一个对象方法跟其他车子比较车速,返回速度差,一个类方法比较两辆车的车速,返回速度差

 #import <Foundation/Foundation.h>

 //类的声明
@interface Car : NSObject
{
int _speed;//速度
}
- (void)setSpeed:(int)newSpeed;
- (int)speed;
//对象方法
/*
作用:比较两辆车的速度大小,返回差值
方法名:differenceSpeedWithOtherCar:
参数:(Car *)otherCar
返回值:int
*/
- (int)differenceSpeedWithOtherCar:(Car *)otherCar; //类方法
/*
作用:比较两辆车的速度大小,返回差值
方法名:differenceSpeedWithCar1: :
参数:(Car *)Car1 (Car *)Car2
返回值:int
*/
+ (int)differenceSpeedWithCar1:(Car *)Car1 andCar2:(Car *)Car2;
@end //类的实现
@implementation Car
//对象方法的实现
- (void)setSpeed:(int)newSpeed
{
_speed = newSpeed;
} - (int)speed
{
return _speed;
} //对象方法
- (int)differenceSpeedWithOtherCar:(Car *)otherCar
{
return [self speed] - [otherCar speed];//self指向调用者也就是本对象
} //类方法 + (int)differenceSpeedWithCar1:(Car *)Car1 andCar2:(Car *)Car2;
{
return [Car1 speed] - [Car2 speed];//通过类调用的话,只能传进来两个参数,因为默认成员变量是0,没有任何实际意义。
} @end int main()
{
Car *p1 = [Car new];
[p1 setSpeed:]; Car *p2 = [Car new];
[p2 setSpeed:]; Car *p3 = [Car new];
[p3 setSpeed:]; int res = [p1 differenceSpeedWithOtherCar:p2];//使用对象调用方法
NSLog(@"%d",res); res = [Car differenceSpeedWithCar1:p1 andCar2:p3];//使用类调用方法
NSLog(@"%d",res);
return ;
}

二、继承

子类从父类继承一些公共属性和方法。

不允许子类和父类拥有同名的成员变量。

方法可以和父类的方法同名(重写),调用过程是先找子类的,再找父类的。

继承的使用场合

  1、当两个类拥有相同的属性和方法时,可以将相同的东西抽象到一个类中

  2、当类a中含有类B所需的全部或部分属性和方法时,可以让B继承A

继承与组合区别

  继承:A 是 B;

  组合:A 拥有B;

示例

 #import <Foundation/Foundation.h>

 //Animal类的声明
@interface Animal : NSObject
{
int _age;//年龄
double _weight;//体重
}
//对象方法
- (void)setAge:(int)newAge;
- (int)age; - (void)setWeight:(int)newWeight;
- (double)weight; - (void)run;
@end //Animal类的实现
@implementation Animal
//方法实现
- (void)setAge:(int)newAge
{
_age = newAge;
}
- (int)age
{
return _age;
} - (void)setWeight:(int)newWeight
{
_weight = newWeight;
}
- (double)weight
{
return _weight;
} - (void)run
{
NSLog(@"动物在奔跑!");
} @end //Dog类的声明
@interface Dog : Animal
{
//int _age;//子类不能和父类的成员变量重名
int gouPai;//狗牌
}
//对象方法
- (void)run;//重写父类的方法
@end //Dog类的实现
@implementation Dog
//方法实现
- (void)run
{
NSLog(@"Dog在奔跑!");
} @end //Cat类的声明
@interface Cat : Animal
{ }
//对象方法 @end //Cat类的实现
@implementation Cat
//方法实现 @end int main()
{
Dog *d = [Dog new];
[d setAge:];
[d run];//子类的run会覆盖父类的run方法
NSLog(@"%d",[d age]); return ;
}

super关键字

如果在子类中想访问父类的方法(对象方法和类方法都可以),可以使用关键字super进行调用 ;  

[super walk];//具体是对象方法还是类方法取决于调用时所处于的环境。

使用场景:子类使用父类的方法时想保留父类的一些操作

 //方法实现
- (void)run
{
NSLog(@"Dog在奔跑!"); [super run];//super 关键字,调用父类的方法
}

三、多态

  父类指针指向子类对象:多态

1、没有继承就没有多态

2、父指针指向子类对象

3、优点:函数/方法传入父指针,则在调用时可以传入子类指针和父类指针

4、缺点:父类类型的变量,不能直接调用子类特有的方法

代码示例

 #import <Foundation/Foundation.h>
/*
多态 */ //Animal类的声明
@interface Animal : NSObject
{
// int _age;//年龄
//double _weight;//体重
}
//对象方法 - (void)eat;
@end //Animal类的实现
@implementation Animal
//方法实现
- (void)eat
{
NSLog(@"吃吃吃!");
} @end //Dog类的声明
@interface Dog : Animal
{
//int _age;//子类不能和父类的成员变量重名
//int gouPai;//狗牌
}
//对象方法
- (void)eat;//重写父类的方法
@end //Dog类的实现
@implementation Dog
//方法实现
- (void)eat
{
NSLog(@"Dog在吃吃吃!"); // [super eat];//super 关键字,调用父类的方法
} @end //Cat类的声明
@interface Cat : Animal
{
//int _age;//子类不能和父类的成员变量重名
//int gouPai;//狗牌
}
//对象方法
- (void)eat;//重写父类的方法
- (void)run;
@end //Dog类的实现
@implementation Cat
//方法实现
- (void)eat
{
NSLog(@"Cat在吃吃吃!"); // [super eat];//super 关键字,调用父类的方法
}
- (void)run
{
NSLog(@"Cat在跑!");
}
@end int main()
{
//Dog *d = [Dog new]; //父类指针指向子类对象:多态
Animal *a = [Dog new];
//[a run];//父类指针调用子类的特有方法,会有警告 Dog *d = (Dog *)a;//可以强制转换,调用子类特有的方法
[d eat]; return ;
}
上一篇:##DAY12 UITableViewCell自定义


下一篇:Linux常用的18个命令(复习)