实现函数调用的命名空间

命名空间的作用就是为了防止函数调用冲突,在swift中,可以通过extension对原始类型进行扩展方法,在对函数命名的时候难免会出现命名冲突,当然可以通过在方法名前添加前缀解决,但是这样总感觉没有那么美观,那么下面我来介绍一下如何实现模拟命名空间的写法来定义函数的扩展。

我直接拿Alamofire框架中的部分代码来介绍,首先我们需要定义一个类型的包装struct,它的作用就类似一个命名空间的效果,将需要扩展的类包起来。

public struct AlamofireExtension<ExtendedType> {
    /// Stores the type or metatype of any extended type.
    let type: ExtendedType

    init(_ type: ExtendedType) {
        self.type = type
    }
}

type:就是我们对应的要包装的类。接下来定义一个协议,协议中规定我们的命名空间的名称,这里提供了两种,一种是静态的,一种是实例的

public protocol AlamofireExtended {
    /// Type being extended.
    associatedtype ExtendedType

    /// Static Alamofire extension point.
    static var af: AlamofireExtension<ExtendedType>.Type { get set }
    /// Instance Alamofire extension point.
    var af: AlamofireExtension<ExtendedType> { get set }
}

af:就是命名空间调用名字,它其实对应的就是一个类型的包装struct,这里通过定义关联类型ExtendedType来确定我们的包装类型,接下来通过extension对这个协议进行扩展,对af的get set方法进行默认实现。

public extension AlamofireExtended {
    /// Static Alamofire extension point.
    static var af: AlamofireExtension<Self>.Type {
        get { return AlamofireExtension<Self>.self }
        set {}
    }

    /// Instance Alamofire extension point.
    var af: AlamofireExtension<Self> {
        get { return AlamofireExtension(self) }
        set {}
    }
}

静态方法返回的是这个包装类型的元类型(即:Class类型),用于调用该类型的静态方法

实例方法返回的是这个包装类型的实例,用于调用该类型的实例方法

接下来我们来看看如果给URLSessionConfiguration的扩展方法添加af的命名空间

extension URLSessionConfiguration: AlamofireExtended {}
extension AlamofireExtension where ExtendedType: URLSessionConfiguration {
    /// Alamofire‘s default configuration. Same as `URLSessionConfiguration.default` but adds Alamofire default
    /// `Accept-Language`, `Accept-Encoding`, and `User-Agent` headers.
    public static var `default`: URLSessionConfiguration {
        let configuration = URLSessionConfiguration.default
        configuration.headers = .default

        return configuration
    }
}

1、让URLSessionConfiguration类实现AlamofireExtended协议,从而添加af命名空间的调用,然后再对类型包装struct进行扩展,从而间接的对URLSessionConfiguration添加方法,where ExtendedType: URLSessionConfiguration,这个是说明只有类型包装struct的type是或者继承自URLSessionConfiguration类的时候,给命名空间包装类添加default静态方法。

在调用的时候类似于下面:

1 URLSessionConfiguration.af.default

这样就为URLSessionConfiguration类添加了一个命名空间为af的调用方法default,从而避免了与URLSessionConfiguration类自身的default方法冲突

以此类推,可以通过类似方式,为其他类型添加af命名空间。

如有不对,请多指教!