一、封装
封装:隐藏对象的属性和实现细节,仅对外公开接口,控制程序中属性的读和修改的访问级别。
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
images/loading.gif' data-original="http://images2015.cnblogs.com/blog/1003661/201608/1003661-20160818182314250-72897259.png" width="287" height="354" />
注解:
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. 父类指针指向子类对象不能使用子类独有的方法,但可以使用强制转换类型,进而调用
原标题:OC对象的三大特性:封装、继承和 多态
关键词: