Class Swift和使用类扩展

Class Swift和使用类扩展,class,swift,alamofire,class-extensions,Class,Swift,Alamofire,Class Extensions,我不明白程序员为什么在类实现中使用扩展关键字。您可以在其他主题中看到代码在语义上更为独立等等。但是当我使用自己的代码时,使用//MARK-Something会让我感觉更清楚。然后,当您在Xcode中使用方法列表(ctrl+6)时,第一眼就能看到所有内容 在Apple文档中,您可以阅读: 扩展向现有类、结构或枚举类型添加新功能 那么,为什么不直接在自己的类中编写自己的代码呢?与我希望扩展某些外部类的功能时不同,例如NSURLSession或Dictionary,在这些类中必须使用扩展 Mattt

我不明白程序员为什么在类实现中使用
扩展
关键字。您可以在其他主题中看到代码在语义上更为独立等等。但是当我使用自己的代码时,使用
//MARK-Something
会让我感觉更清楚。然后,当您在Xcode中使用方法列表(ctrl+6)时,第一眼就能看到所有内容

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

扩展向现有类、结构或枚举类型添加新功能

那么,为什么不直接在自己的类中编写自己的代码呢?与我希望扩展某些外部类的功能时不同,例如
NSURLSession
Dictionary
,在这些类中必须使用扩展


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

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

class ViewController: UIViewController {
...
}

extension ViewController: UITableViewDelegate {
...
}

extension ViewController: UITableViewDataSource {
...
}

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

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

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

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

class ViewController: UIViewController {
...
}

extension ViewController: UITableViewDelegate {
...
}

extension ViewController: UITableViewDataSource {
...
}

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

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

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

使用扩展可以让您将协议一致性声明放在实现该协议的方法旁边

如果没有扩展,想象一下将您的类型声明为:

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

}

因此,您必须在同一扩展中实现这两个协议。

好的,因此当您的类源代码只有几页长时,您就看不到该类实现了哪些协议。您必须通过代码搜索此信息。对我来说,这并不比在code.Horses中使用//MARK更清楚,但我认为使用这种语言而不是注释来表示意图更清楚。另请参阅我的编辑,根据我的经验,它使协议的实施变得更容易。谢谢你的意见。我将尝试结合这两种方法-使用扩展并用//mark.Ok标记它们,所以当您的类源代码只有几页长时,您就看不到该类实现了哪些协议。您必须通过代码搜索此信息。对我来说,这并不比在code.Horses中使用//MARK更清楚,但我认为使用这种语言而不是注释来表示意图更清楚。另请参阅我的编辑,根据我的经验,它使协议的实施变得更容易。谢谢你的意见。我将尝试将这两种方法结合起来——使用扩展并用//mark标记它们。那么NSCoding协议呢?您不能将扩展用于此协议。这是一个棘手的问题,扩展无法添加指定的初始值设定项,因此NSCoding的
init(coder:)
不应该通过扩展来实现,我自己也不太确定。如果您需要从正在扩展的类中访问任何私有内容,这是不起作用的,是吗?还是我遗漏了什么?没错,这在Swift 3中是新的。您需要使用
fileprivate
关键字来访问扩展名中的内容(显然,如果您在同一个文件中有这些扩展名)。在以前的swift版本中,默认情况下,
private
意味着文件是私有的。NSCoding协议是什么?您不能将扩展用于此协议。这是一个棘手的问题,扩展无法添加指定的初始值设定项,因此NSCoding的
init(coder:)
不应该通过扩展来实现,我自己也不太确定。如果您需要从正在扩展的类中访问任何私有内容,这是不起作用的,是吗?还是我遗漏了什么?没错,这在Swift 3中是新的。您需要使用
fileprivate
关键字来访问扩展名中的内容(显然,如果您在同一个文件中有这些扩展名)。在以前的swift版本中,默认情况下,
private
表示该文件为私有文件。请使用您喜欢的扩展名,但扩展名使其比单纯的
标记更为明确:
,清楚地指定文件的开始位置和结束位置。坦率地说,这不是非此即彼的问题,因为我将同时使用
标记:
扩展名
extension
的另一个优点是,您可以轻松地折叠该代码(例如“编辑器”-“代码折叠…”-“折叠”或单击带阴影的左边距)。使用您喜欢的选项,但该扩展使其比单纯的
标记更明确:
,清楚地指定其开始位置和结束位置。坦率地说,这不是非此即彼的问题,因为我将同时使用
标记:
扩展名
extension
的另一个优点是,您可以轻松地折叠该代码(例如,“编辑器”-“代码折叠…”-“折叠”或单击阴影左侧边距)。