Day6 oc继承

oc继承(面向对象的三大特征封装、继承、多态)

摘自:文/FoolPermi(简书作者)
原文链接:http://www.jianshu.com/p/568077956a9a
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
@private私有成员,不能被外部函数访问,也不能被子类继承;
@protected保护成员,不能被外部函数访问,可以被子类继承;
@public共有成员,能被外部函数访问,可以被子类继承;
注意:写在实现中@implementation@end的成员变量默认是私有的
oc中,所有的成员方法(消息)都是共有的
OC的方法都是虚方法:
1.父类的指针可以指向子类的对象
2.调用方法时不看指针看对象
//父类,有一个方法jump
//Father.h
#import <Foundation/Foundation.h>
@interface Father : NSObject

- (void)jump;

@end

//Father.m
#import "Father.h"
@implementation Father

-(void)jump
{
    NSLog(@"Father can jump 1.2m.");
}

@end

//子类,重写了jump方法
//Son.h
#import"Father.h"
@interface Son : Father
//重写,无需声明
@end

//Son.m
#import "Son.h"
@implementation Son

-(void)jump
{
    NSLog(@"Son can jump 1.8m.");
}

@end

//main.m
#import <Foundation/Foundation.h>
#import "Father.h"
#import "Son.h"

int main(int argc,const char* argv[])
{
    @autoreleasepool{
        Son* son = [[Son alloc]init];
        Father* father = son;//父类的指针指向子类的对象
        [father jump];//调用父类的jump还是子类的jump?
        //调用的仍然是子类的方法
        //调用方法时不看指针,看对象
        //对象的地址调用对象的方法
    }
    return 0;

}
  这样的方法叫做虚方法,可以描述不同事物被相同事件触发,产生不同的响应(结果)。下面写一个殴打小动物的程序。
//父类,Animal,有一个beBeaten方法,描述被打时的响应
//Animal.h
#import <Foundation/Foundation.h>
@interface Animal : NSObject

-(void)beBeaten;//被打时的响应

@end

//Animal.m
#import "Animal.h"
@implementation Animal

-(void)beBeaten
{
    return ;//虚方法,可以什么都不做,每个子类都会重写这个方法
}

@end

//Cat.h
#import "Animal.h"
@interface Cat : Animal

@end

//Cat.m
#import "Cat.h"
@implementation Cat

-(void)beBeaten
{
    NSLog(@"Bark and jump to high!");
}

@end

//Dog.h
#import "Animal.h"
@interface Dog : Animal

@end

//Dog.m
#import "Dog.h"
@implementation Dog

-(void)beBeaten
{
    NSLog(@"Give a hard bit!");
}

@end

//Frog.h
#import "Animal.h"
@interface Frog : Animal

@end

//Frog.m
#import "Frog.h"
@implementation Frog

-(void)beBeaten
{
    NSLog(@"Do nothing!");
}

@end

//Human类,有一个方法beat
#import <Foundation/Fountion.h>
#import "Animal.h"
@interface Human : NSObject

-(void)beatAnimal:(Animal*)animal;//父类的指针可以指向任意一个子类的地址,否则,殴打不同的动物,就需要创建不同的动物对象

@end

//Human.m
#import "Human.h"
@implementation Human
//只需要写一个方法,尽管动物不同,这就是父类可以指向子类的好处
-(void)beatAnimal:(Animal*)animal
{
    NSLog(@"Human beat the %@",[animal class]);
    [animal beBeaten];
}

@end

//main.m
#import <Foundation/Foundation.h>
#import "Dog.h"
#import "Cat.h"
#import "Frog.h"
#import "Human.h"
int main(int argc,const char* argv[])
{
@autoreleasepool{
    Frog* frog = [[Frog alloc]init];
    Dog* dog = [[Dog alloc]init];
    Cat* cat = [[Cat alloc]init];
    Human* Linda = [[Human alloc]init]; //who is Linda?
    [Linda beatAnimal:frog];//不同的事物被相同的事件触发,产生不同的响应
    [Linda beatAnimal:cat];
    [Linda beatAnimal:dog];
    }
    return 0;
}
注意:
1、oc中继承不允许子类和父类拥有相同名称的成员变量,而java中是允许的
2、父类必须声明在子类的前面
3、调用某个对象方法时,优先在当前对象中找,若没有去父类中找
4、继承使类之间的耦合性增大
5、每个对象都有个isa指针,isa指针变量在NSObject中,所有类继承自NSObject,都拥有isa指针,isa指向该对象的类,类中存储着成员变量和方法,对象通过isa指针找到对应的方法调用。

多态

多态是在继承的基础上,父类指针指向子类对象

Person *p = [Man new];

同样

NSObject *n = [Man new];

注意:

1、如果函数、方法参数中使用的是父类类型,可以传入父类、子类对象

2、父类类型对象不能直接调用子类特有(不是重写的)方法,必须强制转换为子类类型变量后,才能调用

      编译会报错,运行依旧,但不推荐写。(因为oc是弱类型)

      如上面两句调用 [n eat]编译只会有警告,仍然能动态检查执行man的eat方法。

猜你喜欢

转载自magicbird.iteye.com/blog/2282123