Swift并使用类扩展

时间:2015-02-06 14:27:42

标签: class swift alamofire class-extensions

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

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

  

“扩展程序为现有的类,结构或枚举类型添加新功能。”

那么为什么不直接在我自己的类中编写我自己的代码呢?不像我想扩展某些外国类的功能,例如NSURLSessionDictionary 使用扩展名。

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

2 个答案:

答案 0 :(得分:14)

对我而言,似乎完全合理,因为您可以使用扩展将不同的逻辑部分暴露给不同的扩展。这也可用于使类协议更易读,例如

class ViewController: UIViewController {
...
}

extension ViewController: UITableViewDelegate {
...
}

extension ViewController: UITableViewDataSource {
...
}

extension ViewController: UITextFieldDelegate {
...
}

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

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate {}

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

答案 1 :(得分:6)

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

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

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
    } 

}

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

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.
    }
}

是的,您可以使用// 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
        }
    }
}

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