OC:继承和多态碰到的坑

今天(2018.12.5)算是正式开始学OC了,加油!

#import <UIKit/UIKit.h>
#import "AppDelegate.h"

@interface A : NSObject
- (void) whoAreYou;
@end

@implementation A

- (void) whoAreYou {
    printf("AAA\n");
}
@end

@interface B : A
- (void) sayHello;
@end

@implementation B

- (void) whoAreYou {
    printf("BBB\n");
}

- (void) sayHello {
    printf("Hello\n");
}
@end

int main(int argc, char * argv[]) {
    A *a, *b; // 编译器希望a和b都指向A类型的内存空间
    a = [[A alloc] init];
    b = [[B alloc] init]; // 然而我让b指向B类型的类型空间,好在B是A的子类,所以共享了部分内存,不会报错
    [a whoAreYou];
    [b whoAreYou]; // 调用的是B重载的whoAreYou函数
    [(B *)b sayHello]; // 此时b的类型是A*,但是他想调用A这片内存之外的的函数(即sayHello),则应该强制类型转换成B*类型,倘若他就想调用父类的方法,就没必要强转。
//    [(B *)a sayHello]; // 这句话会报错,父类的类型不能强转成子类的类型,但是子类的类型可以强转成父类的类型
}

如果b就想调用父类的方法,就没必要强转,因为b目前的类型是A *,是可以指向父类的内存的,因此不会报错,代码如下,则B就不用重写函数了,代码如下:

#import <UIKit/UIKit.h>
#import "AppDelegate.h"

@interface A : NSObject
- (void) whoAreYou;
@end

@implementation A

- (void) whoAreYou {
    printf("AAA\n");
}
@end

@interface B : A
- (void) sayHello;
@end

@implementation B

//- (void) whoAreYou {
//    printf("BBB\n");
//}

- (void) sayHello {
    printf("Hello\n");
}
@end

int main(int argc, char * argv[]) {
    A *a, *b; // 编译器希望a和b都指向A类型的内存空间
    a = [[A alloc] init];
    b = [[B alloc] init]; // 然而我让b指向B类型的类型空间,好在B是A的子类,所以共享了部分内存,不会报错
    [a whoAreYou];
    [b whoAreYou]; // 调用的是父类的函数,不必强转
    [(B *)b sayHello]; // 此时b的类型是A*,但是他想调用A这片内存之外的的函数(即sayHello),则应该强制类型转换成B*类型,倘若他就想调用父类的方法,就没必要强转。
//    [(B *)a sayHello]; // 这句话会报错,父类的类型不能强转成子类的类型,但是子类的类型可以强转成父类的类型
}

又发现一个好玩的,来证明父类的类型不能强转成子类的

#import <UIKit/UIKit.h>
#import "AppDelegate.h"

@interface A : NSObject
- (void) whoAreYou;
@end

@implementation A

- (void) whoAreYou {
    printf("AAA\n");
}
@end

@interface B : A
- (void) sayHello;
@end

@implementation B

- (void) whoAreYou {
    printf("BBB\n");
}

- (void) sayHello {
    printf("Hello\n");
}
@end

int main(int argc, char * argv[]) {
    A *a, *b; // 编译器希望a和b都指向A类型的内存空间
    a = [[A alloc] init];
    b = [[B alloc] init]; // 然而我让b指向B类型的类型空间,好在B是A的子类,所以共享了部分内存,不会报错
    [(B *)a whoAreYou]; // 我让a强转成(B*),输出的竟然是AAA,说明强转失败啦,还是那句话,父类的类型不能强转成子类的
    //[(B *)a sayHello]; // 这句话会报错,因为不能强转
}

引入一个id类型的看看?

#import <UIKit/UIKit.h>
#import "AppDelegate.h"

@interface A : NSObject
- (void) whoAreYou;
@end

@implementation A

- (void) whoAreYou {
    printf("AAA\n");
}
@end

@interface B : A
- (void) sayHello;
@end

@implementation B

- (void) whoAreYou {
    printf("BBB\n");
}

- (void) sayHello {
    printf("Hello\n");
}
@end

@interface C : NSObject
- (void) printName;
@end

@implementation C

- (void) printName {
    printf("shijie");
}

@end


int main(int argc, char * argv[]) {
    A *a, *b; // 编译器希望a和b都指向A类型的内存空间
    id c;
    a = [[A alloc] init];
    b = [[B alloc] init]; // 然而我让b指向B类型的类型空间,好在B是A的子类,所以共享了部分内存,不会报错
    c = [[C alloc] init];
    [c printName];
}

猜你喜欢

转载自blog.csdn.net/shijie97/article/details/84957633