黑马程序员————IOS学习笔记 第4篇OC面向对象三大特性(2) - Cache One

       ------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ------- 

一、继承

         在面向对象的过程中,若类A继承类B, 则类A有B的全部属性和方法。B是A的父类,A是B的子类。例如:猫有一般动物的属性,则动物可以使猫的父类;学生具有人的属性,则学生可以使人的子类,学生可以继承人....继承是OC面向对象最基本的特点。如之前见到的 Student : NSObject  ,其中NSLog就是student的父类,因此student就可以使用方法new来创建student的对象。而且基本上所有类的根类是NSObject

书写格式:子类名:父类名

使用注意:

不允许子类与父类有相同名称的成员变量 

使用场合:

1>当两个类有相同的属性和方法时,就可以将相同的属性和方法抽取到一个父类中

2>当一个类拥有另外一个类的属性和方法,可以考虑让让后者继承前者

继承的好处:

 1> 抽取重复代码

 2> 建立了类之间的关系

 3> 子类可以拥有父类中的所有成员变量和方法

坏处:

类与类之间的耦合性太强,即太相互依赖,一旦某个父类发生变化或者丢失,则子类进行继承时会出错

二、重写

子类重新实现父类中的某个方法,覆盖以前的做法叫做重写,因此前提必须是在继承的环境下。

注意:

1>父类必须声明在子类的前面

2>类不能拥有和父类相同的成员变量

3>调用某个对象的方法时,优先当前类去找,如果找不到去上一级类中去找,即可以有相同的方法名,在对象使用方法时优先从调用的它的类找,如果没有则从父类找到方法

三、组合  

在一些场合中继承未必能用,如:成绩类有英语成绩、数学成绩,学生类也包含以上属性,显然有相同的属性,若用继承的思想则认为学生继承了成绩,很显然这不符合逻辑,因此,在一些环境下想要保证性能,但不能用继承,因此可以考虑组合。组合是类A将类B作为它的成员变量,因此A也可以使用B的成员变量和属性。

组合:把一个类拥有另一个类的属性

继承的使用场合

 1> 当两个类拥有相同属性和方法的时候,就可以将相同的东西抽取到一个父类中

 2> 当A类完全拥有B类中的部分属性和方法时,可以考虑让B类继承A类。注意:有时候不符合逻辑,则要考虑组合!

如下是继承和组合的表达:
 A
 {
    int _age;
    int _no;
 }
 
 B : A
 {
    int _weight;
}

 继承:B 是 A

 组合:B 拥有 A
 
 组合的形式

 A
 {
     int _age;
     int _no;
 }
 
 B
 {
     A *_a;
     int _weight;
 }

四、self关键字

self是一个指针,它能够指向当前所在的对象或类
意:

1>谁调用了当前方法,self就代表谁

如:self出现在对象方法中,self就代表对象

      self出现在类方法中,self就代表类

2> 在对象方法利用"self->成员变量名"访问当前对象内部的成员变量

3>注意self的使用会引发死循环,方法自己指向自己会引起死循环,如:

 - (void)test
{
    NSLog(@"调用了-test方法");
    [self test];
}//会引起死循环


下面是狗这个类利用self关键字实现的功能:
@interface Dog : NSObject
- (void)bark;
- (void)run;
@end

@implementation Dog
- (void)bark
{
    NSLog(@"汪汪汪");
}
- (void)run
{
    [self bark];
    //NSLog(@"汪汪汪");
    NSLog(@"跑跑跑");
}
@end

int main()
{
    Dog *d = [Dog new];
    
    [d run];
    
    return 0;
}
其中方法run是对象方法,在[ d  run ]时,则self指向对象d的方法bark。

五、super 关键字

在用继承来描述对象时,有时方法中可能在某些父类方法的基础上添加新东西,在此可以用super关键字,与self类似,是指针。

1.super的作用:

 1>直接调用父类中的某个方法

 2>super处在对象方法中,那么就会调用父类的对象方法;super处在类方法中,那么就会调用父类的类方法

2.使用场合:

子类重写父类的方法时想保留父类的一些行为。

例如:植物大战僵尸中僵尸是父类 而跳跃僵尸、舞王僵尸、铁桶僵尸都可以继承僵尸,在继承走是时可以继承僵尸走,但是还要跳跃、跳舞等动作

代码:

// 僵尸
@interface Zoombie : NSObject
- (void)walk;
@end

@implementation Zoombie
- (void)walk
{
    NSLog(@"往前挪两步******");
}
@end

// 跳跃僵尸
@interface JumpZoombie : Zoombie
@end
@implementation JumpZoombie
- (void)walk
{
    // 跳两下
    NSLog(@"跳两下");
    
    // 走两下(直接调用父类的walk方法)
    [super walk];
}
@end
跳跃僵尸就是在僵尸的基础上添加了跳两下的动作,然后在使用super walk]就可以实现父类的walk了。

六、多态

1.允许子类类型的对象赋值给父类类型的指针,如果参数中使用的是父类类型,可以传入父类、子类对象,这是多态的好处。

#import <Foundation/Foundation.h>
// 动物
@interface Animal : NSObject
- (void)eat;
@end

@implementation Animal
- (void)eat
{
    NSLog(@"Animal-吃东西----");
}
@end

// 狗
@interface Dog : Animal
- (void)run;
@end

@implementation  Dog
- (void)run
{
    NSLog(@"Dog---跑起来");
}
- (void)eat
{
    NSLog(@"Dog-吃东西----");
}
@end

// 猫
@interface Cat : Animal

@end

@implementation Cat
- (void)eat
{
    NSLog(@"Cat-吃东西----");
}
@end

// 这个函数是专门用来喂动画
// 如果参数中使用的是父类类型,可以传入父类、子类对象
void feed(Animal *a)
{
    [a eat];
}
int main()
{
    Animal *aa = [Animal new];
    feed(aa);
    
    Dog *dd = [Dog new];
    feed(dd);
    Cat *cc = [Cat new];
    feed(cc);    
     // 多态:父类指针指向子类对象
    Animal *a = [Dog new];
    [a eat];<span style="font-family: Arial, Helvetica, sans-serif;">// 调用方法时会检测对象的真实形象,在Animal中有方法eat,虽然Dog内也有,但是会调用前者</span>

    
    return 0;
}

2.局限性:父类类型的变量不能用来调用子类的方法,必须强转为子类类型变量后,才能直接调用子类特有的方法。如下:

Animal *aa = [Dog new];
   [aa run];
则可以将aa转化为dog指针的类型,之后便可以调用子类的方法

    Dog *dd = (Dog *)aa;
    [dd run];