引用上一篇文章,下面通过alloc 和initWithName的方式来创建Person对象
- (instancetype)initWithName:(NSString *)name {
if (self = [super init]) {
_name = name;
_headImg = [UIImage imageNamed:@"default_head"]
}
retrun self;
}
虽然禁用了init方法,但是通过super调用父类的init并不会影响。如果经常使用这个方法用类来创建
+(instancetype)initWithName:(NSString *)name
既然有了类方法,实例方法就不需要了
#import <Foundation/Foundation.h>
@class UIImage
NS_ASSUME_NONNULL_BEGIN
@interface Persion : NSObject
@property (nonatomic, strong, nullable) UIImageView *headImg;
@property (nonatomic, copy, nonnull) NSString *name;
- (instancetype)initWithName:(NSString *)name NS_UNAVAILABLE;
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)new NS_UNAVAILABLE;
+ (instancetype)personWithName:(NSString *)name;
@end
NS_ASSUME_NONNULL_END
因为之前- (instancetype)initWithName: 的实现,我们希望加入新的
错误代码
+ (instancetype)personWithName:(NSString *)name {
Person *p = [[ Persion alloc]initWithName:name];
return p
}
原因,解决办法
+ (instancetype)personWithName:(NSString *)name {
Person *p = [[self alloc]initWithName:name];
return p
}
将Persion 换成self
self 表示当前类,而不一定是Person类
在举一个例子
Animal 类init 不可用
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface Animal : NSObject
@property (nonatomic, copy) NSString *name;
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)animalWithName:(NSString *)name;
@end
NS_ASSUME_NONNULL_END
- (instancetype)animalWithName:(NSString *)name {
Animal *animal = [[self alloc]init];
animal.name = name;
return animal;
}
此时如果换成animalWithName: 方法里面 [[self alloc]init]; 换成
[[Animal alloc]init]; 会报错,错误很明显,
在创建一个类Dog继承与Animal
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface Dog : Animal
@end
NS_ASSUME_NONNULL_END
此时用下面代码依然会报错原因init方法父类禁用了
Dog *dog = [[Dog alloc]init];
假设在animalWithName: 方法中用的是[[Animal
alloc]init],那么用它来创建Dog实例肯定是不对的,因为当前类是Dog。如果用self 来创建的话则没有此问题,因为对于Dog来说self 指的是Dog,self
代表具体当前的那一个类,=因此返回结果是Dog实例
思考加入我们就是Animal类init不可用,但是Dog类可以使用???
可以在Dog 头文件再声明一次
@interface Dog : Animal
- (instancetype)ini;
@end
但是编译器会告诉我们ini没有实现的警告!我们知道NSObject 类默认实现的,此处报警告从主观的意识上有一些不合理,但毕竟是负责的编译器,为了防止这样的警告可以手动去除警告。
#pragma clang diagnostic ignored "-Wincomplete-implementation"
总结
- 类方法中的self 指的是当前类,而不是国定的某一个类还可以是这个类的子类;
- 对于父类禁用的方法,需要在子类头文件中再次声明才可以使用,并需要在类实现消除编译警告。