------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
oc 面向对象特性 封装、继承、多态
一、封装
不封装的缺点
当把一个类自己的属性暴漏给外部的时候,那么该类就是去对属性的管理,将数据隐藏其阿里,只能用此方法的函数次啊可以访问或者设置数据,不可被外部任意存储是面下昂对象设计的本质,降低了数据被无用的可能性!
封装的原理: 实例变量默认只能被当前类的对象方法访问。
1.封装的步骤
设置实列变量(setter)和访问实例变量(getter)方法
1)setter方法的设置
命名规范
1.方法名必须以set开头;
2.set后面更上成员变量名称,首字母大写
3.返回值一定是void
4.一定要接受一个参数,而且参数类型需要和成员变量类型一致
5.形参名不能和成员变量名一样
6.set方法实现中,一定要用形参给实例变量赋值。
set方法的好处
1.不让数据暴露在外,保证数据的安全性
2.对设置的数据进行过滤
2)getter方法的书写
1.get方法一定是一个对象方法
2.get方法一定有返回值,返回hi类型和实例变量的类型一致
3.get方法名 是去掉下划线的实例变量名
4.get方法一定没有参数
5.get方法的实现中,一定有返回值的。
setter 和getter 的代码
#import
typedef enum {KsexWomen,KsexMan}Sex;
@interface Person : NSObject
{
NSString *_name;
int _age;
Sex _sex;
float _height;
}
//setter方法的声明
- (void)setName:(NSString*)name;
- (void)setAge:(int)age;
- (void)setSex:(Sex)sex;
- (void)setHeight:(float)height;
//getter方法的声明
- (NSString*)name;
- (int)age;
- (Sex)sex;
- (float)height;
@end
#import "Person.h"
@implementation Person :NSObject
//setter方法的实现
- (void)setName:(NSString*)name{
_name = name;
}
- (void)setAge:(int)age{
_age =age;
}
- (void)setSex:(Sex)sex{
_sex = sex ;
}
- (void)setHeight:(float)height{
_height =height;
}
//getter方法的实现
- (NSString*)name{
return _name;
}
- (int)age{
return _age;
}
- (Sex)sex{
return _sex;
}
- (float)height{
return _height;
}
@end
#import
#import "Person.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person * person =[Person new];
//利用setter方法设置参数。
[person setName:@"小蜜蜂"];
[person setAge:18];
[person setSex:KsexMan];
[person setHeight:178.2f];
NSLog(@"姓名:%@ ,年龄:%d ,性别 %d ,体重%.2f",[person name],[person age],[person sex],[person height]);
}
return 0;
}
2.组合关系
组合:把具有相同基类的对象组合到树形结构中,表示“部分以整体”的层次结构,使用用户对单个对象组合和对象的使用具有一致性
何时使用组合:想把对象成树形结构 ,具有“部分一整体”的层次关系
想让客户端统一处理组合中的对象
组合优点:客户端可以统一的使用组合对象或单个对象,而不组合结构不暴露其内部表现
可以很容易在组合体内加入基友相同的抽象类型的对象
3.依赖关系
a对象作为b对象的局部变量或是方法形参的,b依赖于a 这时候我们称a于b之间存在一种依赖关系
代码
#import
#import "Iphone.h"
@interface Gril : NSObject
{
NSString *name;
Iphone*_iphone;
}
-(void)callToTuHao:(Iphone*)iphone and:(NSString*)iphoneMun;
-(void)sendMassagetoTuHao:(Iphone*)iphone and:(NSString*)iphoneNum;
@end
import "Gril.h"
@implementation Gril
-(void)callToTuHao:(Iphone*)iphone and :(NSString*)iphoneMun{
NSLog(@"给%@土豪a打电话 说!",iphoneMun);
}
-(void)sendMassagetoTuHao:(Iphone*)iphone and:(NSString*)iphoneNum{
NSLog(@"给%@土豪b发短信 。。。。",iphoneNum);
}
@end
#import
@interface Iphone : NSObject
{
NSString*_iphoneName;
}
-(void)setIphoneName:(NSString*)iphoneName;
-(void)callPhone;
-(void)sendMassage;
@end
#import "Iphone.h"
@implementation Iphone
-(void)setIphoneName:(NSString*)iphoneName{
_iphoneName = iphoneName;
}
-(void)callPhone{
}
-(void)sendMassage{
}
@end
#import
#import "Gril.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Iphone * iphone7plus=[Iphone new];
Gril * gril =[Gril new];
[gril callToTuHao:iphone7plus and:@"133338089"];
}
return 0;
}
4.关联关系
关联关系 当一个对象拥有另外一个对象的时候,
当b对象为a对象的成员变量的时候,b对象于a对象之间存在一种关联关系
用关联关系 实现 美女b有一台ipad 并用ipad听英语的过程 代码
#import
@interface Ipad : NSObject
{
NSString*_ipadName;
}
//设置ipad 的名字
- (void)setIpadName:(NSString*)ipadName;
- (void)playMusic;
- (void)playMovie;
- (void)playGame;
@end
#import "Ipad.h"
@implementation Ipad
- (void)setIpadName:(NSString*)ipadName{
_ipadName = ipadName;
}
- (void)playMusic{
NSLog(@"正在用%@播放音乐。。",_ipadName);
}
- (void)playMovie{
NSLog(@"正在用%@播放电影。。。",_ipadName);
}
- (void)playGame{
NSLog(@"正在用%@玩游戏。。",_ipadName);
}
@end
#import
#import "Ipad.h"
@interface Person : NSObject
{
NSString*_name; //姓名
Ipad* _ipad; //有ipad
}
//设置姓名和 ipad
- (void)setName:(NSString*)name;
- (void)setIpad:(Ipad*)ipad;
//听音乐
- (void)ListenMusic;
@end
#import "Person.h"
@implementation Person
//设置姓名和 ipad
- (void)setName:(NSString*)name{
_name = name;
}
- (void)setIpad:(Ipad*)ipad{
_ipad =ipad;
}
- (void)ListenMusic{
[_ipad playMusic];
}
@end
5.oc中没有方法重载
//重载:在一个类中定义同名的方法,方法参数的类型不同。
二、self 和super关键字的使用
1.self 在对象方法中使用
self指代的是调用当前方法的那过对象
2.self用在类方法中
self 指代的时当前的类
self=Person
3.self修饰变量
setter方法中形参名一般不能和成员变量名相同,如果相同则通过self访问成员变量
speed =speed ;
self->speed 访问的时实例变量 加上self就便是访问的就是类的实例变量
4.self 使用总结和注意事项
1)self的使用总结
self 谁调用当前方法 self就代表谁
self在对象方法中,self代表当前对象
self在类方法中,self代表类
[self 方法名];调用其他方法/对象方法
2)self使用注意
同时有对象方法和类方法存在的时候,self不会掉错
#import
@interface Person : NSObject
{
NSString*_name;
}
- (void)setName:(NSString *)name;
- (void)run ;
- (void)eat;
@end
#import "Person.h"
@implementation Person
- (void)setName:(NSString *)name{
_name =name ;
}
- (void)run {
NSLog(@"人在走!!!");
}
- (void)eat{
NSLog(@"人在吃");
//self 指代是对象p1
[self run];
}
@end
#import
#import "Person.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
//当p先吃东西再走。。吃和走是一个对象
Person *p1=[Person new];
[p1 setName:@"xxx"];
// slef指代p1
[p1 eat];
}
return 0;
}
三、继承
继承。子类获得父类特性的概念就是继承
派生类方法属性=基类方法属性+派生类自己的新增的方法和属性
注意: 1)基类的私有属性不能被继承,不能被使用。
2)oc中的继承是单继承:也就是说一个类只能有一个父类,不能继承多个父类
3)继承的合理性
方法重写 把父类的方法,在子类中重新实现了,这种做法就称之为:方法重写
1.继承的主意事项
1)子类不能定义和父类同名的变量,但是可以继承父类的变量
2)oc类支持单一继承不支持多继承
3)oc支持多层继承
2.继承体系中的方法调用的顺序
1)在自己的类中找
2)如果没有,去父类中找
3)如果父类中没有,就去父类的父类找
4)如果父类的父类也没有,就往上找,直到找到基类(NSOject)
5)如果NSObject都没有就报错
3.实例变量修饰符
@public 公开的,在任何地方通过实例变量都可以访问
@protected 受保护类型,表示只能在当前类和子类中访问
@private 私有的,表示只能在当前类中国使用
1.实例变量修饰符对子类的影响
@public 类型的变量,在子类中可以正常访问和使用
@protected 类型的变量,在子类中使用,不能在其他类中使用
@private 子类可以继承父类的所有实例变量和方法 但是不是所有的都可以访问
@private类型的变量,不能被子类访问。
2.实例变量作用域使用注意事项
1)在@interface @end之间声明的成员变量如果不做特别的说明,那么其默认是protected的
2)一个类继承了另一个类,那么就拥有了父类的所有成员变量和方法,注意所有成员变量它都拥有,只是有的他不能访问
3.oc中的私有变量
在.m中定义实例变量 是纯私有变量,该变量只能在当前类中使用,不能被子类继承,也不能被访问
父类的的一个方法 ,没有在.h文件中声明,在.m中实现了 他是不能被子类继承和访问的
4.description方法重写
Dog *d = [Dog new];
//查看对象的地址
NSLog(@"\n%p",d)
NSLog(@"\n%@",d);//打印d对象 //调用了对象的description方法
类名 对象地址
当我们以%@的格式,答应了对象d,此时调用了对象的description方法,对象中如果没有重写父类的description方法,则调用父类的
需求:当我们以%@格式打印 对象的时候,输出对象的所有属性信息
重写父类的description
- (NSString*)description{
NSString *str =[NSString stringWithFormat :@"年龄:%d,颜色%d,",_age,_color]
return str ;
}
打印类 [d class];--->Dog 以%@的方式
NSLog(@"\n%@",[d,class]);
类方法不能重写
多态
1.多态:多态就是某一类食物的多种形态 ,
程序中的多态 :不同对象以自己的方式响应相同名称方法的能力称为多态
2.多态的条件
有继承关系、有重写方法,父类的声明变量指向了子类对象
代码体现 :用父类类型的指针指向了子类对象,这就是多态
Dog *a=[Dog new];
Animal *a = [Dog new]; //Animal是Dog的父类
3.多态的优点
多态的主要好处是 :简化了编程接口 ,他容许在类和类之间重用一些习惯的命名
多态也使得代码可以分散在不同的对象中而不用试图在一个函数中考虑到所有可能的对象
4.类的本质
1.类的本质其实也是一个对象(类对象)
类对象是一种数据据结构,存储类的基本信息:类大小,类名称,类的版本及消息与函数的映射表
类对象代表类,class代表对象,类方法属于类对象
类对象只能使用类方法,不能用实例方法
Person * p = [ Person new];
p是实例对象
Person 也是一个对象(类对象),是Class 类型
如何获取类对象
同过实例 Dog * d =[ Dog new]; Dog* d1 =[Dog new];
//第一种方法获取类对象
Class c =[d class]; Class c1 = [d1 class];
NSLog(@" %p",c); NSLog(@" %p",c1); c 和c1 的地址是一样的 是同一个Dog类对象
第二种方法 通过类名类获取类对象
Class c2 =[Dog class] //Dog
2.类对象的使用
Person *p = [Person new];
Class c1 = [p class]; c1--> Person
1)创建实例对象
Person *p1 =[c1 new];
2)调用类方法 + test 是类方法
[c1 test] //c1 当Person 来用的。
3.SEL类型
SEL 其实是对方法的一种包装,将方法包装成一个SEL类型的数据,去寻找对应的地址,找到方法地址后就可以调用方法,这些都是运行时特性,发送消息就是发送SEL,然后根据SEL找到地址,调用方法
//手动把test方法包装成 SEL 类型
SEL s1 =@selector(est);
//响应方法
[p2 performSelector];