------ <a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a> 期待与您交流! -------
一.封装
1.封装的介绍
(1)为什么要进行封装?
防止类失去对属性的管理权,如果不封装,类的属性可能会被无限制的修改
(2)封装的原理:
在类中,属性(实例变量)默认不能被外部访问
(3)封装的概念:
给类中每个实例变量提供设置值和获取值的方法
2.封装的步骤
定义设置实例变量(setter)方法和访问实例变量(getter)的方法
(1)setter方法(设置器)
在开发过程中,考虑到安全性要求,我们一般不在成员变量名前面使用
@public、@protected等关键字修饰,而是使用Set方法来为对象供成员
变量的值。在set方法的内部也可 以对一些不合理的赋值进行筛选过滤。
Set方法的作用:为外界供一个设置成员变量值的方法
setter方法的书写规范:
1)set方法一定是一个对象方法
2)set方法的返回值一定是void类型
3)set方法的方法名一定以set开头 + 是去掉下划线的实例变量名并且首字母大写
4)set方法一定有参数,参数的类型一定和实例变量的类型保持一致
5)set方法的参数 一般是去掉下划线的实例变量名
6)set方法的实现,一定是用方法的形参给实例变量赋值
Set方法的好处:
1)不让数据暴露在外,保证了数据的安全性
2)对设置的数据进行过滤
(2)getter方法(访问器)
getter方法的书写规范
1)get方法一定是一个对象方法
2)get方法一定有返回值,返回值类型一定要和实例变量的类型一致
3)get方法名称一定是去掉下划线的实例变量
4)get方法一定没有参数
5)get方法的实现,一定是返回值实例变量的值
(3)注意
1)在实际的开发中,不一定set和get方法都会供,如果内部的成员变量比如学生的学号
这样的数据只允许外界读取,但是不允许修改的情况,则通常只供get方法而不供set方法。
2)成员变量名的命名以下划线开头,get方法名不需要带下划线,使用下划线开头有两个好处:
1>与get方法的方法名区分开来;
2>可以和一些其他的局部变量区分开来,下划线开头的变量,通常都是类的成员变量。
3.封装的实现举例
//注:为使代码方便看,将.h和.m中的代码放在.m文件里了
#import <Foundation/Foundation.h>
@interface Person : NSObject
{
//定义两个实例变量
int _age; //年龄
NSString *_name;//名称
}
//_age实例变量,应该封装一组方法
// 一个是设置 _age 值的方法
-(void)setAge:(int)age;
-(void)setName:(NSString *)name;
// 一个是获取 _age 值的方法
-(int)age;
-(NSString *)name;
@end
#import "Person.h"
@implementation Person
//_age实例变量,应该封装一组方法
// 一个是设置 _age 值的方法
-(void)test{
// int age;
// _age
}
-(void)setAge:(int)age{
//对将要设置的值,进行过滤
//只有age>0的时候,才能给_age赋值
if(age>0){
_age = age;
}
}
-(void)setName:(NSString *)name{
_name = name;
}
//get方法的实现
-(int)age{
return _age;
}
-(NSString *)name{
return _name;
}
@end
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
//创建一个对象
Person *p = [Person new];
//调用设置 age 的方法
[p setAge:1];
// 调用 获取age值的方法
NSLog(@"age = %d",[p age]);
}
return 0;
}
二.封装和对象之间的关系
1.组合模式
(1)组合模式定义
把具有相同基类类型的对象组合到树形结构中,以表示"部分-整体"
的层次结构,使得用户对单个对象和组合对象的使用具有一致性。
组合模式使得树形结构中的每个节点都具有相同的抽象接口,整个
结构可作为一个统一的抽象结构使用,而不暴露其内部表示。每个
节点的任何操作,可以通过抽象基类中定义的相同接口来进行。
(2)何时使用组合模式
想把对象抽象成树形结构,具有“部分-整体”的层次关系。
想让客户端统一处理组合中的对象。
(3)在ios中使用组合模式
在CocoaTouch框架中,UIView对象被组合成一个树形结构,UIView对
象可以包含其他的UIView对象。这种组合方式便于统一用于事件处
理和动作消息,例如处理渲染事件时,事件会在父视图中被处理,然
后在传递给子视图,因为他们都是相同的类型,事件可以传递到树形
结构的每一视图。
(4)组合模式优点
客户端可以统一的使用组合对象或单个对象,
而不暴露组合结构其内部表示。
可以很容易在组合体内加入具有相同抽象类型的对象.
客户端不必因为加入了新的对象而更改代码
(5)组合模式与装饰模式(Decorator)
Composite模式和Decorator模式虽然逻辑完全不同,但是从类图中
可以看到它们有着相似的结构,Composite模式重在构造类,而
Decorator模式重在不生成子类即可给对象添加职责。所以两种模
式侧重点不一样,Decortor模式重在修饰,而Composite模式重在表示。
4.依赖关系
(1)依赖关系概念
A对象作为B对象的局部变量或是方法形参的,B依赖与A,
这时候我们称A与B之间存在一种依赖关系
(2)面向对象设计中的几个概念:
耦合度:当修改一个对象的时候,对另外一个对象的影响程度
低耦合:当修改一个对象的对其他对象影响比较小
高内聚:一个对象仅仅做自己相关的事情
注:面向对象设计原则:单一职责原则
5.关联关系
关联关系的概念
关联关系,HasA关系:当一个对象拥有另外一个对象的时候,当B对
象为A对象的成员变量的时候,B对象与A对象之间存在一种关联关系
注:
关联关系是面向对象中最常用一种关系
关联关系的耦合度要高于依赖关系
三.继承
1.继承的代码实现
2.基类和派生类之间的关系
一般情况下,基类和派生类之间的关系如下:
注意:
1)基类的私有属性能被继承,不能被使用。2)OC中的继承是单继承:也就是说一个类只能一个父类,不能继承多个父类3)继承的合理性: 引用一句话来述继承:“龙生龙,凤生凤”.
3.方法的重写
方法的重写,从父类继承的方法,可能这个方法并不适合子类,可以在子类中重写父类的方法。
重写之后,父类的对象调用父类的方法;子类的对象,调用子类的方法,不会引起冲突。从父类继承的方法,不适用于子类时,可以直接声明父类的同名方法,并定义。不用考虑父类中,方法已存在的问题。
重写后,子类可以通过super调用父类的方法。
4.继承的注意事项:
1) 子类不能定义和父类同名的变量,但是可以继承父类的变量
2) OC中类的继承是单一的(支持单一继承),但是可以支持多层继承
5.继承体系中方法调用的顺序
1)在自己类中找
2)如果没有,去父类中找
3)如果父类中没有,就去父类的父类中
4)如果父类的父类也没有,就还往上找,直到找到基类(NSObject)
5)如果NSObject也没有就报错了
6.实例变量的作用域
(1)实例变量修饰符
1) @public 共有的,在任何地方都可以访问
2) @protected受保护的,只能在同一个类或者其子类中使用(默认)
3) @private私有的,修饰的实例变量,只能在当前类中使用
(2)实例变量修饰符的作用域的问题
从修饰的位置开始,到遇到起其他的修饰符就结束了,如果没有遇
到其他的修饰符,那么作用域到它所在的代码块"}"的位置结束了
7.实例变量修饰符对子类的影响
1)@private私有成员是能被继承,不能被外部函数访问。
2)@public公有成员能被继承,也能被外部方法访问。
3)@protected保护成员能够被继承、在子类中使用,但不能够被外部函数访问。
总结: 子类继承父类,子类会从父类获取父类的所有的属性和方法
但是,并不是所有的属性,都可以使用(父类的@private修饰的,在子类中可以看到,但是不能使用)
8.实例变量作用域使用注意事项
(1)在@interface@end之间声明的成员变量如果不做特别的说明,
那么其默认是 protected的。
(2)一个类继承了另一个类,那么就拥有了父类的所有成员变量和
方法,注意所有的成员变量它都拥有,只是有的它不能直接访问。
9.OC中的私有变量
在类的实现即.m@implementation中也可以声明成员变量,但是因
为在其他文件中通常都只是包含头文件而不会包含实现文件,所以
在.m文件中声明的成员变量是@private的。在.m中定义的成员变
量不能和它的头文件.h中的成员变量同名,在这期间使用@public
等关键字也是徒劳的。
注:私有变量既不能看到也不能使用
10.OC中的私有(相对私有)方法
OC中私有方法实现有两种方式:
1)方法在.m中实现,不在.h中声明(相对私有)
2)通过匿名类别(延展)实现私有(一般意义上的私有)
11.description方法
(1)description方法概述
description方法是基类NSObject所带的方法,因为其默认实现是
返回类名和对象的内存地址,这样的话,使用NSLog输出OC对象,意
义就不是很大,因为我们并不关心对象的内存地址,比较关心的是
对象内部的一些成变量的值。因此,会经常重写description方法,
覆盖description方法的默认实现
(2)description陷阱
千万不要在对象description方法中同时使用%@和self,下面的写法是错误的:
- (NSString *)description {
return [NSString stringWithFormat:@"%@", self];
}
同时使用了%@和self,代表要调用self的description方法,因此最终会导致程
序陷入死循环,循环调用description方法.
12.继承的应用
例
/注:为使代码方便看,将.h和.m中的代码放在.m文件里了
#import <Foundation/Foundation.h>
@interface Animal : NSObject
{
//定义实例变量
@public
int _age;
@protected
float _weight;
@private
float _sanwei;
}
//显示所有的属性值
-(void)disp;
//设置属性值
-(void)set;
@end
#import "Animal.h"
@implementation Animal
//显示所有的属性值
-(void)disp{
NSLog(@"%d,%.2f,%.2f",_age,_weight,_sanwei);
}
//设置属性值
-(void)set{
//给实例变量赋值
_age = 18;
_weight = 34.34f;
_sanwei = 80;
}
@end
#import "Animal.h"
@interface Person : Animal
@end
#import "Person.h"
@implementation Person
-(void)disp{
NSLog(@" age = %d",_age);
NSLog(@" weight = %.2f",_weight);
}
@end
#import <Foundation/Foundation.h>
#import "Animal.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Animal *ani = [Animal new];
[ani set]; //设定属性值
[ani disp]; //显示属性值
}
return 0;
}
四.多肽
1.程序中的多态的概念
不同的对象以自己的方式响应相同名称方法的能力称为多态
2.多态的条件
有继承关系
有方法重写
父类的声明变量指向子类对象
3.多态的优点
4.多态的原理多态的主要好处就是简化了编程接口.它容许在类和类之间重用一些习
惯性的命名,而不用为每一个新加的函数命名一个新名字。这样,编程
接口就是一些抽象的行为的集合,从而和实现接口的类的区分开来。
多态也使得代码可以分散在不同的对象中而不用试图在一个函数中考虑到所有
可能的对象。这样使得您的代码扩展性和复用性更好一些。当一个新的情景出
现时,您无须对现有的代码进行改动,而只需要增加一个新的类和新的同名方法。
动态绑定:
动态类型能使程序直到执行时才确定对象所属类型动态类型绑定能使程序直到执行时才确定要对对象调用的实际方法
OC不同于传统程序设计语言,它可以再运行时加入新的数据类型
和新的程序模块:动态类型识别,动态绑定,动态加载
id类型:通用指针类型,弱类型,编译时不进行类型检查
5.多态的注意点
1)如果存在多态,父类是可以访问子类特有的方法
2)如果不存在多态,父类是不可以访问子类特有的方法的