Swift并使用类扩展

Den*_*eny 14 class class-extensions swift alamofire

我不明白为什么程序员extension在他们的类实现中使用关键字.您可以阅读其他主题,然后代码在语义上更加分离等等.但是当我使用自己的代码时,我觉得使用它会更清晰// MARK - Something.然后当你在Xcode中使用方法列表(ctrl + 6)时,一切都会在第一眼看到.

在Apple文档中,您可以阅读:

"扩展程序为现有的类,结构或枚举类型添加了新功能."

那么为什么不直接在我自己的类中编写我自己的代码呢?不像我想扩展一些外国类的功能,比如,NSURLSession或者Dictionary,你必须使用扩展.

Mattt Thompson在他的Alamofire图书馆中使用扩展,也许他可以给我一点解释,为什么他选择这种方法.

lib*_*bec 14

对我来说,这似乎是完全合理的,因为您可以使用扩展将不同的逻辑部分暴露给不同的扩展.例如,这也可以用于使协议的类一致性更具可读性

class ViewController: UIViewController {
...
}

extension ViewController: UITableViewDelegate {
...
}

extension ViewController: UITableViewDataSource {
...
}

extension ViewController: UITextFieldDelegate {
...
}
Run Code Online (Sandbox Code Playgroud)

为了清楚起见,协议方法在不同的扩展中分开,这似乎比我们说的要好得多:

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate {}
Run Code Online (Sandbox Code Playgroud)

所以,我要说使用扩展来使你自己的代码更具可读性是没有害处的,而不仅仅是扩展SDK中现有的类.使用扩展可以避免在控制器中放置大量代码并将功能拆分为易于阅读的部分,因此使用它们没有任何缺点.


Air*_*ity 7

使用扩展允许您在实现该协议的方法旁边保留协议一致性声明.

如果没有扩展名,请将您的类型声明为:

struct Queue<T>: SequenceType, ArrayLiteralConvertible, Equatable, Printable, Deflectable, VariousOtherables {

// lotsa code...

// and here we find the implementation of ArrayLiteralConvertible
    /// Create an instance containing `elements`.
    init(arrayLiteral elements: T…) {
        etc
    } 

}
Run Code Online (Sandbox Code Playgroud)

将此与使用扩展进行对比,您可以将协议的实现与实现它的特定方法捆绑在一起:

struct Queue<T> {
   // here go the basics of queue - the essential member variables,
   // maybe the enqueue and dequeue methods 
}

extension SequenceType {
    // here go just the specifics of what you need for a sequence type
    typealias Generator = GeneratorOf<T>
    func generate() -> Generator {
        return GeneratorOf { 
          // etc.
        }
    }
}

extension Queue: ArrayLiteralConvertible {
    init(arrayLiteral elements: T...) {
        // etc.
    }
}
Run Code Online (Sandbox Code Playgroud)

是的,你可以标记你的协议实现// MARK(并记住,你可以结合使用这两种技术),但你仍然会分裂到文件的顶部,协议支持的声明将是,文件的正文,您的实施在哪里.

另外,请记住,如果您正在实施协议,那么您将从IDE中获得有用的(如果有些详细的)反馈,告诉您还有什么需要实现的.使用扩展来逐个执行每个协议使得它(对我来说)比一次性完成(或者在添加它们时从上到下来回跳跃)容易得多.

鉴于此,将其他非协议但相关的方法分组为扩展也是很自然的.

实际上,当你不能这样做时,我偶尔会感到沮丧.例如,

extension Queue: CollectionType {
    // amongst other things, subscript get:
    subscript(idx: Index) -> T {
        // etc
    }
}

// all MutableCollectionType adds is a subscript setter
extension Queue: MutableCollectionType {
    // this is not valid - you’re redeclaring subscript(Index)
    subscript(idx: Int) -> T {
        // and this is not valid - you must declare
        // a get when you declare a set
        set(val) {
            // etc
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

所以你必须在同一个扩展中实现它们.