Swift and using class extension

给你一囗甜甜゛ 提交于 2019-12-17 12:44:09

问题


I don't understand why programmers use the extension keyword in their class implementation. You can read in other topics that code is then more semantically separated and etc. But when I work with my own code, it feels clearer to me to use // MARK - Something. Then when you use methods list (ctrl+6) in Xcode, everything is seen at first look.

In Apple documentation you can read:

“Extensions add new functionality to an existing class, structure, or enumeration type.”

So why not write my own code directly inside my own class? Unlike when I want to extend functionality of some foreign class, like NSURLSession or Dictionary, where you have to use extensions.

Mattt Thompson use extension in his Alamofire library, maybe he can give me little explanation, why he chose this approach.


回答1:


For me it seems completely reasonable since you can use extensions to expose different parts of logic to different extensions. This can also be used to make class conformance to protocols more readable, for instance

class ViewController: UIViewController {
...
}

extension ViewController: UITableViewDelegate {
...
}

extension ViewController: UITableViewDataSource {
...
}

extension ViewController: UITextFieldDelegate {
...
}

Protocol methods are separated in different extensions for clarity, this seems to be far better to read than lets say:

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

So, I'd say there's no harm in using extensions to make your own code more readable, not just to extend already existing classes from SDK. Using extensions you can avoid having huge chunks of code in your controllers and split functionality into easily readable parts, so there's no disadvantage of using those.




回答2:


Using extensions allows you to keep your declaration of protocol conformance next to the methods that implement that protocol.

If there were no extensions, imagine declaring your type as:

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
    } 

}

Contrast this with using extensions, where you bundle together the implementation of the protocols with those specific methods that implement it:

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

Yes, you can mark your protocol implementations with // MARK (and bear in mind, you can combine both techniques), but you would still be split across the top of the file, where the declaration of protocol support would be, and the body of the file, where your implementation is.

Also, bear in mind if you’re implementing a protocol, you will get helpful (if slightly verbose) feedback from the IDE as you go, telling you what you’ve got left to implement. Using extensions to do each protocol one by one makes it (for me) far easier than doing it all in one go (or hopping back and forth from top to bottom as you add them).

Given this, it’s then natural to group other, non-protocol but related methods into extensions as well.

I actually find it frustrating occasionally when you can’t do this. For example,

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

So you have to implement both within the same extension.



来源:https://stackoverflow.com/questions/28367950/swift-and-using-class-extension

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!