黑马程序员——OC基础02—封装、继承、多态

时间:2023-02-12 14:21:14

——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-

一、面向对象三大特性之封装

1)封装的作用

之前用的@public的成员可以任意被赋值,是因为隐藏的数据底层复杂的东西暴露出一个借口,不封装的话就会失去对属性的管理权,具有很大的风险。
这时候我们需要set和get方法来管理成员的访问,过滤掉不合理的东西。

2)封装的原理:实例变量智能呗当前类的对象进行访问。
set方法的作用:为外界提供一个设置成员变量值的方法;

set方法的声明注意事项:

a 方法名必须以set开头 ,是一个对象方法;
b set后面跟上成员变量(去掉下划线)的名称,首字母大写
c 返回值一定是void
d 参数类型需要和成员变量的类型一致
e 形参名不能与成员变量名一样(成员变量名去掉下划线);
f 行参名不能与实例变量名同名


get方法的声明注意事项

a 方法名以get开头 ,是一个对象方法;
b 方法名是去掉下划线的实例变量名;
c 有返回值,返回值和成员变量的类型一致;
d get方法没有参数;
e get方法实现中,一定是返回实例变量的值。

例如


#import <Foundation/Foundation.h>

//声明对象的属性和行为
@interface Car : NSObject
{

//声明对象属性,成员变量默认是protected,且成员变量不能初始化,不能在外部被直接调用,不能使用static关键字进行修饰
// @public
int _wheel;
int _speed;

}

//wheel的set方法
- (void)setWheels:(int)wheel;
//wheels的get方法
- (int)wheel;

//speed的set方法
- (void)setSpeed:(int)speed;
//speed的get方法
- (int)speed;
@end

set方法的好处:
(1)不让数据暴露在外,保证了数据的安全性
(2)对设置的数据进行过滤

3)set 方法和get方法的实现:

@implementation Car 


//set方法
- (void)setWheel:(int)wheel
{

_wheel = wheel; //给实例变量赋值
}
//get方法
- (int)wheel
{
return _wheel;
}


//speed的set方法
- (void)setSpeed:(int)speed
{
_speed = speed;
}
//speed的get方法
-(int)speed
{
return _speed;
}
@end

4)set 方法和get方法的调用

int  main()  
{

Car *c = [Car new];


// c->wheel = 4;
// c->speed = 200;
//之前一直采用调用成员变量,只有成员变量是public 时,才可以调用成员变量

//调用对象的方法,改变成员变量的值
[c setWheel:3 andSpeed:500];


//匿名对象
// [Car new]->wheels =18;


//调用get set 方法
[c setWheels:10];
[c setSpeed:1000];

NSLog(@"%d,%d",[c wheel],[c speed]);
return 0;
}

二、类方法
1.直接可以用类名来执行的方法
2.与对象方法不同:

以‘+’开始;
只能用类名调用,对象不能调用;
类方法中不依赖于对象,执行效率要比对象方法高;
类方法不能访问实例变量(成员变量);
使用场合:当不需要访问实例变量时,尽量使用类方法。




3.类方法的声明与实现

#import <Foundation/Foundation.h>

@interface Car : NSObject
{
@public
int _wheels;
int _speed;

//声明类方法
+ (void)info;

@end



@implementation Car

//实现类方法
+ (void)info
{
NSLog(@"调用了类方法,我是不能访问成员变量的");

}


@end


int main()
{

Car *c = [Car new];

[Car info]; //类方法的调用

return 0;

4.self的用途

1)谁调用了当前方法,self就代表谁;
self出现在对象方法中,self就代表对象;
self出现在类方法中,self就代表类;

2)在对象方法利用self->成员变量名 访问当前对象内部的成员变量;
3)[self 方法名] 可以调用其他对象方法 或者类方法。

@interface Dog : NSObject 
- (void)bark;
- (void)run;
@end

@implementation Dog
- (void)bark
{
NSLog(@"汪~~");
}
- (void)run
{
[self bark];
NSLog(@"跑跑跑");
}
@end

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

[d run];

return 0;
}

三、继承

1.子类拥有父类的所有成员变量和方法
3.子类重新根据自己的属性实现父类中的方法,称之为重写
4.父类被继承了还是能照常使用的
5.当调用某个方法时,优先在子类中寻找,如果子类没有定义该方法,就去父类中寻找
6.OC支持多层继承,NSObject是全部oc类的最终父类
7.子类不能定义和父类相同的变量,但是可以继承父亲的变量。

继承可以抽取重复的代码,建立类之间的相互关系,使得代码更简洁,设计更合理。例子代码如下:


#import <Foundation/Foundation.h>

//声明对象的属性和行为
@interface Car : NSObject
{

int _wheels;
int _speed;
}

- (void)drive;

+ (void)test;
@end

//实现类
@implementation Car

- (void)drive
{
NSLog(@"汽车在行驶---");
}

+ (void)test
{
NSLog(@"继承的使用");
}
@end


//定义子类 Jeep类
@interface Jeep : Car

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

@end
//实现Jeep类
@implementation Jeep

- (void)drive
{
NSLog(@"Jeep在行驶---");
}

+ (void)test
{
NSLog(@"Jeep在行驶+");
[super test];
}
@end

//定义Benz类
@interface Bmw : Car

- (void)drive;
- (void)fly;
+ (void)test;
@end

@implementation Bmw

- (void)fly{

NSLog(@"我在飞哦~~~");
}
- (void)drive
{
NSLog(@"Bmw 在行驶---");
}

+ (void)test
{
NSLog(@"Bmw在行驶---");
[super test];
}
@end

int main()
{

Jeep *j = [Jeep new];
[j drive];

Bmw *b = [Bmw new];
[b drive];

//super的使用 和类方法的使用
[Jeep test]; //输出 “Jeep在行驶+ 继承的使用”
[Bmw test];
return 0;
}

四、多态

1.多态的定义:不同的对象以自己独特的方式相应相同方法的能力称为多态。
多态是建立在继承的基础之上,多态可以让父类访问子类。

2.多态的实现条件:有继承关系;有方法重写;父类的声明变量指向子类变量

int  main()  
{

//多态的使用
Car *c = [Jeep new];
[c drive]; //输出 Jeep在行驶---

Car *c2=[Jeep new];
[(Jeep*c2)fly];输出:“我在飞哦~~~” //父类也可以访问子类的非继承原理。
但是 Car *c2=[Car new];
(Car*)c2 eat],//在这骗编译器,会提示错误。
return 0;
}