面试题

Category & Extension

2019-06-24  本文已影响0人  六横六竖亚

首先,Category(类别)和Extension(类扩展)是非正式协议的两种写法,目的都是在无需子类化的情况下,给类添加方法(和属性)。

Swift

在Swift中,已经没有了Category的写法,Extension的写法也更加简洁,功能也更加强大。可以用于:

1、代码模块化区分,层次更清晰

2、缺省实现协议中的方法,相当于协议方法的默认实现

3、定义新的实例方法和类方法,或提供新的初始化方法

4、添加属性:普通情况下只能添加计算属性(可读可写,但无具体值,没有存储功能和意义)

var testInt: Int { 

    get { return 0 }

    set { //doSomething } 

}

但特殊情况下,可以利用Runtime动态添加属性(只能是继承于OC的子类或系统类,AnyObject)

注:Swift中利用OC的Runtime特性动态添加属性,含义上和协议中添加属性不太一样,因为协议中的属性目的是为了让外部类是赋值实现,动态添加属性仅仅是为了添加属性。

private var SwiftPropertyNameKey: Void?

protocol AddPropertyProtocol: AnyObject { }

extension AddPropertyProtocol {

    var swiftPropertyName: String? {

        get { return objc_getAssociatedObject(self, &SwiftPropertyNameKey) as? String }

        set { objc_setAssociatedObject(self, &SwiftPropertyNameKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) }

    }

}

OC中的非正式协议

类别(Category)

@interface NSString(StringFrame)

- (CGSize *)getStringFrame(labelWidth: CGFloat); 

@end 

类扩展(Extension)

@interface MyClass() { 

    float value; 

- (void)setValue:(float)newValue; 

@end

类别和类扩展区别

类别中只能增加方法,类扩展不仅可以增加方法,还可以增加实例变量(默认private,作用范围只在当前类)

类别是在运行时把方法添加到类中(所以不能添加属性,但可以不被实现),类扩展是在编译阶段被添加到类中,不实现编译器会有警告。

.h中的类扩展方法是公有的,.m中是私有的(声明私有方法的标准实现)


类别中添加属性

.h中声明

@interface YourClasseBaseNSObject (Category)

@property(nonatomic, copy) NSString *propertyName;  //相当于声明了getter和setter方法

@end

.m中实现(不实现getset运行会因找不到方法而崩溃)

static NSString *propertyNameKey =@"propertyNameKey";

@implementation YourClasseBaseNSObject (Category)

- (void)setPropertyName: (NSString *)propertyName {

        objc_setAssociatedObject(self, &propertyNameKey, propertyName, OBJC_ASSOCIATION_COPY);

}

- (NSString *)propertyName {

    return objc_getAssociatedObject(self, &propertyNameKey);

}

@end

扩展阅读:https://tech.meituan.com/2015/03/03/diveintocategory.html

上一篇下一篇

猜你喜欢

热点阅读