14

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

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

“扩展为现有的类、结构或枚举类型添加了新功能。”</p>

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

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

4

2 回答 2

14

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

class ViewController: UIViewController {
...
}

extension ViewController: UITableViewDelegate {
...
}

extension ViewController: UITableViewDataSource {
...
}

extension ViewController: UITextFieldDelegate {
...
}

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

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

所以,我想说使用扩展使您自己的代码更具可读性并没有什么坏处,而不仅仅是从 SDK 扩展现有的类。使用扩展可以避免在控制器中有大量代码,并将功能拆分为易于阅读的部分,因此使用这些没有缺点。

于 2015-02-06T14:51:44.117 回答
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
    } 

}

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

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

所以你必须在同一个扩展中实现两者。

于 2015-02-06T14:53:40.023 回答