OC是基于C的,在C的基础上进行封装,使其成为一种面向对象的语言。面向对象中比较重要的一点是继承。学习过OC的人都知道OC是没有多继承的。下面将着重介绍一下OC中的继承问题。
子类通过继承父类,便完全拥有父类的成员变量和成员方法(即属性和方法)。比如说猫是一个类型,它有眼睛、耳朵、鼻子等成员变量,并且会“叫”和“捉老鼠”,那么我们科依此定义一个Cat类,在猫的世界里,我们可以根据猫的品种或者猫的颜色对猫进行详细分类。那个最简单的例子,根据猫的颜色,我们可以定义一个白猫类和黑猫类。当然在重新定义这两个类的时候,他们是有共同特征的,都具有猫的共同点,所以我们可以让WhiteCat和BlackCat分别继承Cat类,这样WhiteCat或BlackCat就叫子类,而Cat叫父类,WhiteCat完全具有Cat的成员变量和成员方法,BlackCat也是如此,并且子类可以拥有自己独特的属性或方法,比如说为其添加color属性等。
上面讲述的情况在C和OC中都是通用的,但是对于OC来说,它没有多继承,即一个类不能继承两个或者两个以上的父类,遇到这种多继承的问题是并不是用OC完全不能实现。在OC中,你可以为一个类添加分类,从而间接实现多继承的功能。
分类是OC中特有的知识,通过分类,你可以为一个系统类或者自定义的类进行扩展,为其添加成员方法,依次来实现多继承的功能。它与多继承相比的优点是,我们可以对系统框架中提供的类进行修改,添加新的方法,实现我们所需要的功能;缺点在于你不能通过分类为一个类添加成员变量。下面举个例子。
我们可以为UILabel添加一个根据其显示的内容自适应控件大小的方法,如下所示:
#import <UIKit/UIKit.h>
@interface UILabel (StringFrame)
- (CGSize)boundingRectWithSize:(CGSize)size;
@end
#import "UILabel+StringFrame.h"
@implementation UILabel (StringFrame)
- (CGSize)boundingRectWithSize:(CGSize)size
{
CGSize retSize = CGSizeZero;
if (IOS7_OR_LATER) {
NSDictionary *attribute = @{NSFontAttributeName: self.font};
retSize = [self.text boundingRectWithSize:size
options:\
NSStringDrawingTruncatesLastVisibleLine |
NSStringDrawingUsesLineFragmentOrigin |
NSStringDrawingUsesFontLeading
attributes:attribute
context:nil].size;
} else {
retSize = [self.text sizeWithFont:[UIFont systemFontOfSize:self.font.pointSize]
constrainedToSize:CGSizeMake(size.width, CGFLOAT_MAX)
lineBreakMode:NSLineBreakByWordWrapping];
}
return retSize;
}
@end
这样,就可以通过UILabel的实例对象,调用 - ( CGSize )boundingRectWithSize:( CGSize )size,获得它的宽和高,然后重新调整label的frame。