深入浅出Objective-C笔记(六)

2015-11-19  本文已影响15人  无聊的呆子

类的继承(续)


子类的方法若跟父类的方法名一样,则子类的方法会覆盖掉父类的方法,最终执行子类的方法。

一个例子,只有print方法的子类和父类

#import <Foundation/Foundation.h>

@interface BaseClass : NSObject
- (void) print;
@end

@implementation BaseClass
- (void)print {
    NSLog(@"print in BaseClass");
}

@interface InheritClass : BaseClass
- (void)print;
@end

@implementation InheritClass 
- (void)print {
    NSLog(@"print in InheritClass");
}

int main(int argc, const char *argv[]) {
    @autoreleasepool {
        BaseClass *base = [ [BaseClass alloc] init ];
        InheritClass *inherit = [ [InheritClass alloc] init ];
        [base print];
        [inherit print];
    }
    return 0;
}

输出结果为: print in BaseClass
           print in InheritClass 

** 用super关键字。**

superself很像,都是对当前对象的引用(对自身的引用)。

不一样的是,super会把当前的对象当做父类对象。

举个例子:在上述代码中,加入一行[super print]即可

int main(int argc, const char *argv[]) {
    @autoreleasepool {
        BaseClass *base = [ [BaseClass alloc] init ];
        InheritClass *inherit = [ [InheritClass alloc] init ];
        [base print];
        [inherit print];
        [super print];
    }
    return 0
}

输出结果是:print in BaseClass
          print in InheritClass
          print in BaseClass 

e.g.

#import <Foundation/Foundation.h>

@interface A : NSObject
+ (A*)factoryMethod;//工厂方法可以创建自身类型的对象。工厂方法定义成一个类方法(加号开头)
                      //用来创建当前类的实例对象,所以返回类型是个指针(对象)
- (void)methodA;//这个是实例方法
@end

@implementation A
+ (A*)factoryMethod {
    return [[A alloc] init];//工厂方法的实现(作用)就是返回一个生成的实例对象
}

- (void)methodA {
    NSLog(@"Call MethodA!");//一个简单的实例方法的实现,往控制台输出东西
}
@end

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

@implementation B
- (void)methodB {
    NSLog(@"Call MethodB!");
}
@end 

int main(int argc, const char *argv[]) {
    @autoreleasepool {
        A *a = [A factoryMethod];//调用类A的工厂方法创建类A的实例a
        B *b = [B factoryMethod];//虽然B继承了A,但是这里调用B的工厂方法是有问题的
    }//类B的工厂方法返回值还是类A,因为在定义类A的工厂方法时把返回值写死了
    return 0;//在实现里也把返回值写死了,只能返回类A的实例对象
}

解决办法:在类A中对工厂方法的声明和实现都使用id类型

@interface A : NSObject
+ (id)factoryMethod;
-(void)methodA;
@end

@implementation A
+ (id)factoryMethod {
    return [[self  class] alloc] init];//注意这里,使用了[self class]这条消息 
}
- (void)methodA {
    NSLog(@"Call MethodA!");
}
@end

使用id会有个问题,因为编译器不知道返回的具体类型,所以不能做静态语法检测。

比如在main方法里写[[A factoryMethod] methodB],这其实是错的,因为类A根本就没有methodB ,但是却能编译通过了,因为编译器不知道工厂方法的返回值类型,所以不知道你返回的对象有没有methodB ,就默认通过了。

解决办法:使用instancetype类型。它比较特殊,只能用做方法的返回值来用。** 它表示返回值是这个方法所在类的类型。**

若用instancetype代替类A工厂方法的返回类型id

@interface A : NSObject
+ (instancetype)factoryMethod;

若还在main方法里写[[A factoryMethod] methodB],这时编译器就会报错了,因为instancetype表示了[A factoryMethod]的返回值为factoryMethod这个方法所在类的类型 ,即类A 。类A没有methodB,当然会报错。

id虽然灵活,却可能瞒混编译器,隐藏一些bug,所以有时可以用instancetype代替 。instancetype有种硬点的意思。

上一篇下一篇

猜你喜欢

热点阅读