你的位置:首页 > 操作系统

[操作系统]OC对象的三大特性:封装、继承和 多态


一、封装

封装:隐藏对象的属性和实现细节,仅对外公开接口,控制程序中属性的读和修改的访问级别。

person.h:

1 #import <Foundation/Foundation.h>2 3 @interface Person : NSObject4 /** 年龄 */5 @property (nonatomic, assign) int age;6 7 @end

 

person.m:

 1 #import "Person.h" 2  3 @implementation Person 4  5 #pragma mark - 重写set方法 6 - (void)setAge:(int)age { 7   if (age < 0) { 8     NSLog(@"年龄不能为负数"); 9     return;10   } else {11     _age = age;12     return;13   }14 }15 16 @end

 

优点:

1. 隐藏内部实现细节,设置访问权限,提高了数据的安全性。

2. 任何出入的数据都要流经接口,通过重写set方法可以起到过滤数据的作用。

 

二、继承

继承:指一个对象直接使用另一对象的属性和方法。

Person.h:

1 #import <Foundation/Foundation.h>2 3 @interface Person : NSObject4 /** 年龄 */5 @property (nonatomic, assign) int age;6 /** 吃方法 */7 - (void)eat;8 9 @end

 

Person.m:

 1 #import "Person.h" 2  3 @implementation Person 4  5 #pragma mark - 重写set方法 6 - (void)setAge:(int)age { 7   if (age < 0) { 8     NSLog(@"年龄不能为负数"); 9     return;10   } else {11     _age = age;12     return;13   }14 }15 16 #pragma mark - 吃方法实现17 - (void)eat {18   NSLog(@"Person 吃饭");19 }20 21 @end

 

GoodPerson.h:

1 #import "Person.h"2 3 // 继承父类Person4 @interface GoodPerson : Person5 /** 姓名 */6 @property (nonatomic, strong) NSString *name;7 8 @end

 

 

GoodPerson.m:

1 #import "GoodPerson.h"2 3 @implementation GoodPerson4 5 - (void)eat {6   NSLog(@"GoodPerson 吃饭");7 }8 9 @end

 

main.m:

 1 #import <Foundation/Foundation.h> 2 #import "Person.h" 3 #import "GoodPerson.h" 4  5  6 int main(int argc, const char * argv[]) { 7   /** 人 */ 8   Person *p = [[Person alloc] init]; 9   p.age = 20;10   [p eat];11   12   /** 好人 */13   GoodPerson *goodP = [[GoodPerson alloc] init];14   goodP.age = 30;15   [goodP eat];16   17   // 好人姓名18   goodP.name = @"Lkun";19   NSLog(@"好人name = %@", goodP.name);20   21   22   return 0;23 }

 

编译运行结果:

2016-08-18 17:53:37.484 01-discription[634:455001] Person 吃饭2016-08-18 17:53:37.485 01-discription[634:455001] GoodPerson 吃饭2016-08-18 17:53:37.485 01-discription[634:455001] 好人name = LkunProgram ended with exit code: 0

 

                    

 

注解:

1. 大部分类都继承自NSObject父类,所以也都继承了该类的属性和方法。

2. GoodPerson虽继承了父类Person的属性age和方法eat,但却有其独特的方法name,且重写了父类的方法eat。

3. 当子类对象收到方法消息时则逐层查找,找到即执行。如setName方法在GoodPerson父类就可以找到,而setAge类得在Person父类才能找到

优点:抽取重复代码、建立联系

缺点:耦合性强 

继承:狗是动物,所以狗继承动物类

组合:学生拥有狗,所以把狗作为学生类的一个属性

 

三、多态

 多态:父类指针指向子类对象,父类类型参数可以接收子类类型参数的传入

Person.h:

1 #import <Foundation/Foundation.h>2 #import "Animal.h"3 4 @interface Person : NSObject5 // 喂食动物的方法6 - (void)feedAnimal:(Animal *)animal;7 8 @end

 

Person.m:

1 #import "Person.h"2 3 @implementation Person4 5 - (void)feedAnimal:(Animal *)animal {6   [animal eat];7 }8 9 @end

 

Animal.h:

1 #import <Foundation/Foundation.h>2 3 @interface Animal : NSObject4 /** 吃方法 */5 - (void)eat;6 7 @end

 

Animal.m:

1 #import "Animal.h"2 3 @implementation Animal4 5 - (void)eat {6   NSLog(@"Animal eat");7 }8 9 @end

 

Cat.h:

1 #import "Animal.h"2 3 @interface Cat : Animal4 5 @end

 

Cat.m:

1 #import "Cat.h"2 3 @implementation Cat4 #pragma mark - 重写父类的吃方法5 - (void)eat {6   NSLog(@"Cat eat");7 }8 9 @end

 

Dog.h:

1 #import "Animal.h"2 3 @interface Dog : Animal4 5 @end

 

Dog.m:

1 #import "Dog.h"2 3 @implementation Dog4 #pragma mark - 重写父类吃方法5 - (void)eat {6   NSLog(@"Dog eat");7 }8 9 @end

main.m:

 1 #import <Foundation/Foundation.h> 2 #import "Person.h" 3 #import "Animal.h" 4 #import "Cat.h" 5 #import "Dog.h" 6  7  8 int main(int argc, const char * argv[]) { 9   /** 人 */10   Person *p = [[Person alloc] init];11   12   /** 动物 */13   Animal *a = [[Animal alloc] init];14   15   /** 猫 */16   Cat *c = [[Cat alloc] init];17   18   // 父类指针指向Dog实例对象19   Animal *d = [[Dog alloc] init];20   21   22   // 动态检测真正对象是Dog23   [d eat];24   25   // 父类指针类型的参数也可以接收子类指针类型的参数26   [p feedAnimal:a];27   [p feedAnimal:c];28   29   30   return 0;31 }

 

编译运行结果:

2016-08-18 19:42:59.467 01-discription[759:669325] Dog eat2016-08-18 19:42:59.468 01-discription[759:669325] Animal eat2016-08-18 19:42:59.468 01-discription[759:669325] Cat eatProgram ended with exit code: 0

 注解:

1. oc语言是编译的时候才动态检测,调用真正的对象,而不管是指针是什么类型。

2. 父类子针作为参数类型时,其子类子针参数都可以传入

3. 父类指针指向子类对象不能使用子类独有的方法,但可以使用强制转换类型,进而调用