面向对象编程之所以成为主流的编程思想和他的继承和多态是分不开的,只要是面向对象语言都支持继承和多态,当然不同的OOP语言之间都有其特点。OC中和Java类似,不支持多重继承,但OOP语言C++就支持多继承,为什么OC不支持多继承稍后将会提到。
说到继承呢,想到了一本书上是引用《大话西游》里的一句话来描述继承的。“人是人他妈生的,妖是妖他妈生的!”,想必里面的唐三藏也学过OOP编程,也许他们师徒四人去西天取什么算法导论呢,漫谈OOP编程啦,数据结构啦等这类的书去啦。人和妖都属于动物类,但各自有各自的特点,各自有各自的不同,动物就是父类,而人和妖就是子类。继承的目的是为了减少代码的冗余,还是DRY原则(don`t repeat yourself)。
在Objective-C中super是指向直接父类的指针,而self是指向本身的指针,self就相当于java中的this指针。在OC中写类时可以在@implementation中定义哪些在@interface中无相应声明的方法,但这个方法是私有的,仅在类的实现中使用。
在Objectiv-C中几乎所有的类都是继承自NSObject类,NSObject类中存在大量功能强大的方法。下面对NSObject类中的各种方法进行试验和介绍:
1. +(void) load; 类加载到运行环境时调用该方法
测试:在子类中重写load方法来进行测试, 当重写完load方法,在mian方法中不需要任何实例化任何对象
当类被加载时load就会别调用.load是类方法,可以直接被类调用
1
2
3
4
5
|
+( void ) load
{
NSLog(@ "ObjectTest中的load方法被调用啦!!" );
}
|
运行结果:
1
|
2014-07-30 08:58:31.704 HelloOC[550:303] ObjectTest中的load方法被调用啦!!
|
2. +(void) initialize; 在类第一次使用该类时调用该方法,第二次就不调用了
测试:重写initalize方法
1
2
3
4
5
|
+( void ) initialize
{
NSLog(@ "initialize方法被调用了(类第一次被实例化)!" );
}
|
运行结果:
1
2
|
2014-07-30 09:27:53.767 HelloOC[624:303] load方法被调用啦!!
2014-07-30 09:27:53.769 HelloOC[624:303] initialize方法被调用了(类第一次被实例化)!
|
3. +(id) alloc: 返回一个已经分配好的内存对象; -(id) init: 对已经分配了内存的实例进行初始化; new同时调用了alloc 和 init
demo: Object *object = [[Object alloc] init];
可以在子类中把alloc进行重写,然后观察运行情况
1
2
3
4
5
6
|
+(id) alloc
{
NSLog(@ "alloc函数被调用啦" );
return [super alloc];
}
|
1
2
3
4
5
6
7
|
-(id) init
{
NSLog(@ "init被调用了" );
self = [super init];
return self;
}
|
测试方法一个用alloc和init实例化类,一个用new实例化类:
1
2
3
4
5
|
ObjectTest *o1 = [[ObjectTest alloc] init];
ObjectTest *o2 = [ObjectTest new ];
|
运行结果:
1
2
3
4
5
6
|
2014-07-30 09:59:58.991 HelloOC[689:303] load方法被调用啦!!
2014-07-30 09:59:58.993 HelloOC[689:303] initialize方法被调用了(类第一次被实例化)!
2014-07-30 09:59:58.993 HelloOC[689:303] alloc函数被调用啦
2014-07-30 09:59:58.993 HelloOC[689:303] init被调用了
2014-07-30 09:59:58.994 HelloOC[689:303] alloc函数被调用啦
2014-07-30 09:59:58.994 HelloOC[689:303] init被调用了
|
4.-(void)dealloc 释放对象自身所占有的内存;
5. -(Class)class 或者 +(Class)class 返回当前对象的所属类; -(Class)superclass 或者 +(Class)superclass返回当前类的父类
1
2
3
4
5
6
7
|
NSString *className =(NSString *) [self class ];
NSLog(@ "%@类的display方法" , className);
NSString *superClassName = (NSString *) [self superclass];
NSLog(@ "%@类的父类是%@" , className, superClassName);
|
6、-(BOOL)isKindOfClass : (Class)aClass 判断某个实例是否属于某个类或者子类的对象
事例代码如下:
1
2
3
4
5
|
BOOL b = [o2 isKindOfClass:[ObjectTest class ]];
if (b == YES) {
NSLog(@ "o2是ObjectTest类的对象" );
}
|
7.-(BOOL)isMemberOfClass:(Class)aClass; 只能判断摸个实例是否属于某个类,不能判断是否属于某个父类;
1
2
3
4
5
|
BOOL result = [o2 isMemberOfClass:[NSObject class ]];
if (result == NO) {
NSLog(@ "isMemberOfClass不能判断是否为NSObject子类的对象" );
}
|
8.-(NSString *) description; 返回字符串形式对象的描述,方便调试
1
2
3
|
NSString *descript = [o2 description];
NSLog(@ "%@" , descript);
|
输出结果: <ObjectTest: 0x100206650>
9.-(NSUInteger) hash; 返回对象的哈希值;
1
2
3
|
NSUInteger hash = [o2 hash];
NSLog(@ "%p" , hash);
|
输出结果:2014-07-30 11:40:35.685 HelloOC[1130:303] 0x100107b70
10.-(BOOL) isEqual:(id)object; 比较两个对象是否相同,默认是使用地址进行比较的,且hash值一定要相同
1
2
3
4
5
6
7
8
9
10
11
|
NSString *str1 = @ "111" ;
NSString *str2 = str1;
if ([str2 isEqual:str1] == YES)
{
NSLog(@ "str2 == str1" );
}
else
{
NSLog(@ "str2 != str1" );
}
|
Objective-C中的继承
继承是is-a的关系,比如猫咪是一个动物,那么动物是父类,而猫咪是动物的子类。子类具有父类的属性和 行为,以及自身的属性和行为,也就是说“父类更一般,子类更具体”。用一个富二代的类来说明一下类的继承。
1.先定义一个富人的类
代码说明:
1.声明访问权限为@protected的三个属性,分别为三个属性用@property加上getter和setter方法
2.并为该类创建便利初始化方法和便利构造器
3.为富人类定义一个刷卡方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
#import <Foundation/Foundation.h>
@interface Richer : NSObject
{
@ protected
NSString *name;
int age;
NSString *gender;
}
@property (copy, nonatomic) NSString *name;
@property (assign, nonatomic) int age;
@property (copy, nonatomic) NSString *gender;
-(id) initWithName : (NSString *)vName
AndAge : ( int )vAge
AndGender : (NSString *)vGender;
+(id) richerWithName : (NSString *)vName
AndAge : ( int )vAge
AndGender : (NSString *)vGender;
-( void ) poss;
@end
|
2.为富人类编写实现代码
代码说明:
1.用@synthesize实现getter和setter方法
2.实现便利初始化方法,用[ super init ]初始化富人类的直接父类,也就是NSObject
3.使用便利构造器返回实例化并初始化后的对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
#import "Richer.h"
@implementation Richer
@synthesize name, age, gender;
-(id) initWithName : (NSString *)vName
AndAge : ( int )vAge
AndGender : (NSString *)vGender
{
if (self = [super init])
{
self->name = vName;
self->age = vAge;
self->gender = vGender;
}
return self;
}
+(id) richerWithName:(NSString *)vName
AndAge:( int )vAge
AndGender:(NSString *)vGender
{
Richer *richer = [[Richer alloc] initWithName:vName
AndAge:vAge
AndGender:vGender];
return richer;
}
-( void ) poss
{
NSLog(@ "%@有钱你就刷吧" , name);
}@end
|
3.编写富二代的类,富二代和富人有许多相似的属性和方法所以富二代继承于富人类,并添加相应的属性和方法,把需要重写的方法进行重写。
代码说明:
1.为富二代类添加新的爱好属性
2.为富二代添加新的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
#import "Richer.h"
@interface Richer2nd : Richer
@property (copy, nonatomic) NSString *hobby;
-(id) initWithName : (NSString *) vName
AndAge : ( int )vAge
AndGender : (NSString *) vGender
AndHobby : (NSString *)vHobby;
+(id)richer2ndWithName : (NSString *) vName
AndAge : ( int )vAge
AndGender : (NSString *) vGender
AndHobby : (NSString *)vHobby;
-( void ) myHobby;
@end
|
4.各种方法的实现
代码说明:
1.在编写便利初始化方法时利用super来调用父类的便利初始化方法来把继承到的父类的方法进行初始化
2.用self给新添加的属性进行初始化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
#import "Richer2nd.h"
@implementation Richer2nd
@synthesize hobby;
-(id)initWithName:(NSString *)vName
AndAge:( int )vAge
AndGender:(NSString *)vGender
AndHobby:(NSString *)vHobby
{
if (self = [super initWithName:vName AndAge:vAge AndGender:vGender]) {
self->hobby = vHobby;
}
return self;
}
+(id)richer2ndWithName:(NSString *)vName
AndAge:( int )vAge
AndGender:(NSString *)vGender
AndHobby:(NSString *)vHobby
{
Richer2nd *richer = [[Richer2nd alloc] initWithName:vName AndAge:vAge AndGender:vGender AndHobby:vHobby];
return richer;
}
-( void )poss
{
[super poss];
NSLog(@ "我是富二代,我爸有钱,我就刷!" );
}
-( void ) myHobby
{
NSLog(@ "我是富二代%@,我超喜欢%@" , name, hobby);
}
@end
|
5.以下是上面代码的运行结果
1
2
3
4
|
2014-07-30 08:38:12.956 HelloOC[483:303] Bill有钱你就刷吧
2014-07-30 08:38:12.957 HelloOC[483:303] BILL`s son有钱你就刷吧
2014-07-30 08:38:12.958 HelloOC[483:303] 我是富二代,我爸有钱,我就刷!
2014-07-30 08:38:12.958 HelloOC[483:303] 我是富二代BILL`s son,我超喜欢飙车
|
Objective-C中的多态
多态简单的说就是对于不同对象响应同一个方法时做出的不同反应。在 OC中动态类型id是实现多态的一种方式,id是一个独特的数据类型,可以转换为任何数据类型,上面的富人和富二代可以这样定义
1
2
3
4
5
6
7
8
9
10
|
id richer = nil;
richer = [Richer richerWithName:@ "Bill" AndAge:40 AndGender:@ "Man" ];
[richer poss];
richer = [Richer2nd richer2ndWithName:@ "BILL`s son" AndAge:16 AndGender:@ "男" AndHobby:@ "飙车" ];
[richer poss];
[richer myHobby];
|
上面程序的输出结果和继承部分的结果是一致的;
多态的另一个例子: Animal是父类,子类有Cat 和 Dog,子分别重写了父类中的eat方法;实例化对象的时候可以用下面的方法:
1
2
3
4
5
6
7
|
Animal *animal = nil;
//实例化猫的对象
animal = [Cat new ];
[animal eat];
//实例化狗的对象
animal = [Dog new ];
[animal eat];
|
面向对象编程中的OCP原则和LSP原则
OCP : Open Closed Principle原则, 对扩展开放,对修改关闭
LSP :里氏代换原则,任何基类可以出现的地方,子类一定可以出现。
|
请发表评论