- 文章学习整理自文顶顶博客园
-
目录
- 面向对象的三大特征:封装(成员变量)、继承、多态
- 在OC语言中,使用@interface 和 @implementation 来处理类。
- @interface 暴露给外界提供展示以及接口
- @implementation 将具体的实现封装起来
一、面向对象--封装(成员变量)
1、set方法
(1) 开发过程中,考虑带安全性,我们一般不在成员变量名前面使用@public、@protected等关键字修饰,而是使用set方法来为对象提供成员变量的值。
在set方法的内部也可以对一些不合理的赋值进行筛选过滤。
(2)set方法的作用:为外界提供一个设置成员变量的方法
(3)命名规范:
1、方法名必须以set开头
2、set后面跟上成员变量的名称,首字母大写
3、返回值一定是void
4、一定要接受一个参数,而且参数类型需要和成员变量的类型一致
5、形参名不能和成员变量一样(苹果官方推荐成员变量名前加"_"以示区分)
(4)set方法的好处
1、不让数据暴露在外,保证了数据的安全性
2、对设置的数据进行过滤
// set方法的声明
#import <Foundation/foundation.h>
@interface Person:NSObject {
int _age;
}
-(void)setAge:(int)age;
-(void)print;
@end
// set方法的实现
#import <Foundation/Foundation.h>
@implementation Person
-(void)setAge:(int)age {
_age = age;
}
-(void)print{
NSLog(@"age = %d",_age),
}
@end
2、Get方法
(1)Get方法的作用:为调用者返回对象内部的成员变量
(2)命名规范:
1、一定有返回值,返回值的类型和成员变量的类型一致
2、方法名和成员变量一样
3、不需要接受任何参数
// Get方法的声明
#import <Foundation/Foundation.h>
@interface Person:NSObject
{
NSString *_name;
}
-(void)setName:(NSString *)name;
-(NSString *)name;
@end
//Get方法的实现
-(void)setName:(NSString *)name {
_name = name;
}
-(NSString *)name {
return _name;
}
3、self关键字
self是一个指针,谁调用了当前方法,self就指向谁
出现在对象对的中,就代表着你当前对象;出现在类方法中,就代表着当前类
二、OC 面向对象---继承
1、基本概念
(1)子类继承了父类父类同样就拥有了父类所有的方法和属性(成员变量)
(2)继承的好处
1、抽取了重复的代码
2、建立了类与类之间的联系
(3)继承的缺点
耦合性太强
(4)OC语言是单继承语言。在OC语言中,基本上所有类的根类都是NSObject类
@interface Animal: NSObject
// 动物继承了NSObject,获得NSObject类的方法
@end
@interface Dog: Animal
// dog类继承Animal类
@end
2、继承的使用使用
(1)编译器从上往下执行,所以在子类前面至少要有父类的声明
(2) OC中不允许子类和父类拥有相同名称的成员变量名;
(3)OC中的子类可以拥有和父类相同名称的方法,在子类调用时,优先去自己的内部寻找,如果没有泽一层一层的往上找;
提示:重写子类重新实现了父类中的某个方法,覆盖了父类以前的实现。
提示:每个类中都有一个super class指针,该指针指向自己的父类。
对象中都有一个isa 指针,该指针指向调用该对象的类。
3、继承和组合
继承的适用场合:
1、当两个类拥有相同的属性和方法时,就可以将相同的属性和方法抽取到一个父类中
2、当A类完全拥有B类中的部分属性和方法时,可以考虑让B类继承A类,在这种情况下,可以考虑使用组合
例: 狗是动物,可以让狗继承动物类
学生有书,可以让书这个类作为学生的属性
4、关键字super
super关键字,在子类中重写方法时,可以让调用者跳过子类这一层而调用父类中的方法。
作用:
(1)直接调用父类中的某一个方法
(2)super处在对象方法中,那么就会调用父类的对象方法;
super处在类方法中,那么就会调用父类的类方法
使用场景:
子类重写父类方法时,想要保留父类的一些行为。
三、面向对象----多态
1、基本概念
(1)多态在代码中的体现,即为多种形态,必须要有继承,没有继承就没有多态
(2)在使用多态时,会进行动态检测,以调用真实的对象方法
(3)多态在代码中的体现---即父类指针指向子类对象
#import <Foundation/Foundation.h>
// 声明一个Animal类,该类继承自NSObject
@interface Animal: NSObject
// Aniaml类中声明一个eat的对象方法
-(void)eat;
@end
// Animal的实现
#import <Foundation/Foudation.h>
@implementation Animal
-(void)eat {
NSLog(@"Animal eat.");
}
@end
// Dog类继承自Animal类
#import <Foundation / Foundation.h>
#import "Animal.h"
@interface Dog : Animal
// 在子类中声明了父类中已经有的eat方法,称之为方法重写
-(void)eat;
-(void)run;
@end
// dog类的实现
#import <Foundation/Foundation.h>
@implementation Dog
-(void)eat {
NSLog(@" Dog eat. ");
}
-(void)run {
NSLog(@" Dog run . ");
}
@end
// 测试程序
#import <Foundation/Foundation.h>
#import "Animal.h"
#import "Dog.h"
int main(int arc, const char * argh[])
{
// Dog类型的指针指向Dog类的对象
Dog *d = [[Dog alloc] init];
[d eat]; // 结果 : dog eat.
// 多态
// 父类指针指向子类对象
Animal *a = [[Dog alloc] init];
[a eat]; // 结果 : dog eat.
// Animal 类型的指针指向Aniaml类型的对象
Animal *a1 = [[Animal alloc] init];
[a1 eat];
}
2、多态使用注意
代码分析:
Dog *d = [[ Animal alloc ] init]; 动物是一条狗?语义正确吗?
NSString *str. = [NSString new]; 狗是一个字符串?正确吗?
OC语言是一种弱语法的语言,编译的时候不会报错,所以要求我们在实际的开发过程中一定要按照既定的规范来写代码。
3、多态的好处
// 需要一个新的函数专门用来喂狗
void feed(Dog *)d
{
[d eat];
}
//如果这个时候也需要喂猫,那就应该重写一个新的函数
void feed(Cat *)c
{
[c eat];
}
/*
而狗和猫实际上都继承自动物这个类,在这里就可以使用多态来简化代码了
这里只需要把函数的参数写成是Animal *类型的,那么Dog和 Cat 类型的对象就都可以传入进来。
调用的时候直接改变参数就可以了。
*/
4、多态的局限性:
父类类型的指针变量不能直接调用子类特有的方法
// 不建议的做法
Animal *a = [[Aniaml alloc] init];
[a run]; // 在Animal类中没有run方法,这里调用了狗对象的方法
解决方法:可以将a强制转换为Dog *类型的变量
Dog *d = (Dog *)a ; // 使用强制转化,这里a和d指向的是同个对象
5、多态使用总结
(1)没有继承就没有多态
(2)代码的体现:父类类型的指针指向子类对象
(3)好处:如果函数方法参数中使用的是父类类型,则可以传入父类和子类对象,而不用再去定义多个函数来和相应的类进行匹配了;
(4)局限性:父类类型的变量不能直接调用子类特有的方法,如果必须使用,则必须强制转换为子类特有的方法。