Objective-C 沒(méi)有抽象類,只是指語(yǔ)言的語(yǔ)法構(gòu)造上沒(méi)有C++/Java那樣專門的abstract class定義,這并不妨礙我們?cè)谟肙bjective-C寫(xiě)程序的時(shí)候使用"abstract class"這一通用的OOP概念,即類的部分實(shí)現(xiàn)需要subclass來(lái)完成。
代碼如下:
// 創(chuàng)建類Person 聲明如下方法
@interface Person : NSObject
- (void)love;
- (void)coding;
- (void)travelling;
- (void)home;
@end
// 在.m文件中最好做如下處理
#define MethodNotImplemented() \
@throw \
[NSException exceptionWithName:NSInternalInconsistencyException \
reason:[NSString stringWithFormat:@"You must override %@ in a subclass", NSStringFromSelector(_cmd)] \
userInfo:nil]
@implementation Person
- (instancetype)init {
self = [super init];
if (!self) return nil;
return self;
}
- (void)work { MethodNotImplemented(); }
- (void)coding {MethodNotImplemented(); }
- (void)love { MethodNotImplemented(); }
- (void)travelling { MethodNotImplemented(); }
- (void)home { MethodNotImplemented(); }
@end
這個(gè)聲明的其實(shí)只是一個(gè)普通的基類,而且可以重寫(xiě)-init方法,那哪里抽象?和普通的類有什么區(qū)別?如果這個(gè)類需要有協(xié)議(代理),需要額外的屬性,以及必須實(shí)現(xiàn)的的抽象方法,又該怎么處理?
下面,我又創(chuàng)建了一個(gè)Person+Private的類,這只是一個(gè).h文件,并未實(shí)現(xiàn)任何的方法。
代碼如下:
#import "Person.h"
@protocol PersonDelegate;
@interface Person ()
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) int age;
@property (nonatomic, weak) id<PersonDelegate> delegate;
- (void)eat;
@end
@interface Person(Abstruct)
- (void)work;
@end
@protocol PersonDelegate <NSObject>
- (void)run;
@end

Snip20171015_2.png

Snip20171015_1.png
配合 MethodNotImplemented() 宏,在OC中的抽象基類就創(chuàng)建好了。在子類中調(diào)用對(duì)應(yīng)的方法之前實(shí)現(xiàn)該抽象類的方法即可。
抽象類在第三方框架中的應(yīng)用分析:
Masonry
在Masonry中的MASConstraint就是一個(gè)抽象類,上例中的Person也是遵照MASConstrain的寫(xiě)法寫(xiě)的一個(gè)示例。
在MASConstraint中作者這樣寫(xiě)的:
@interface MASConstraint : NSObject
- (MASConstraint * (^)(MASEdgeInsets insets))insets;
......
- (MASConstraint *)left;
- (MASConstraint *)top;
- (MASConstraint *)right;
- (MASConstraint *)bottom;
- (MASConstraint *)leading;
- (MASConstraint *)trailing;
- (MASConstraint *)width;
- (MASConstraint *)height;
- (MASConstraint *)centerX;
- (MASConstraint *)centerY;
- (MASConstraint *)baseline;
- (MASConstraint *)firstBaseline;
- (MASConstraint *)lastBaseline;
@end
@implementation MASConstraint
- (MASConstraint * (^)(id))equalTo {
return ^id(id attribute) {
return self.equalToWithRelation(attribute, NSLayoutRelationEqual);
};
}
- (MASConstraint * (^)(id))mas_equalTo {
return ^id(id attribute) {
return self.equalToWithRelation(attribute, NSLayoutRelationEqual);
};
}
- (MASConstraint * (^)(id))greaterThanOrEqualTo {
return ^id(id attribute) {
return self.equalToWithRelation(attribute, NSLayoutRelationGreaterThanOrEqual);
};
}
- (MASConstraint * (^)(id))mas_greaterThanOrEqualTo {
return ^id(id attribute) {
return self.equalToWithRelation(attribute, NSLayoutRelationGreaterThanOrEqual);
};
}
- (MASConstraint * (^)(id))lessThanOrEqualTo {
return ^id(id attribute) {
return self.equalToWithRelation(attribute, NSLayoutRelationLessThanOrEqual);
};
}
- (MASConstraint * (^)(id))mas_lessThanOrEqualTo {
return ^id(id attribute) {
return self.equalToWithRelation(attribute, NSLayoutRelationLessThanOrEqual);
};
}
#pragma mark - MASLayoutPriority proxies
- (MASConstraint * (^)(void))priorityLow {
return ^id{
self.priority(MASLayoutPriorityDefaultLow);
return self;
};
}
- (MASConstraint * (^)(void))priorityMedium {
return ^id{
self.priority(MASLayoutPriorityDefaultMedium);
return self;
};
}
- (MASConstraint * (^)(void))priorityHigh {
return ^id{
self.priority(MASLayoutPriorityDefaultHigh);
return self;
};
}
@end
MASConstraint+Private.h
@protocol MASConstraintDelegate;
// 延展類
@interface MASConstraint ()
@property (nonatomic, assign) BOOL updateExisting;
@property (nonatomic, weak) id<MASConstraintDelegate> delegate;
- (void)setLayoutConstantWithValue:(NSValue *)value;
@end
@interface MASConstraint (Abstract)
- (MASConstraint * (^)(id, NSLayoutRelation))equalToWithRelation;
- (MASConstraint *)addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute;
@end
@protocol MASConstraintDelegate <NSObject>
- (void)constraint:(MASConstraint *)constraint shouldBeReplacedWithConstraint:(MASConstraint *)replacementConstraint;
- (MASConstraint *)constraint:(MASConstraint *)constraint addConstraintWithLayoutAttribute:(NSLayoutAttribute)layoutAttribute;
@end
具體請(qǐng)參看Masonry源碼。