2015-02-06 5 views
12

프로그래머가 클래스 구현시 extension 키워드를 사용하는 이유를 알지 못합니다. 다른 주제에서 코드가 더 의미 론적으로 분리된다는 것을 읽을 수 있습니다. 그러나 자신의 코드로 작업하면 // MARK - Something을 사용하는 것이 더 명확하게 느껴집니다. 그런 다음 Xcode에서 메서드 목록 (ctrl + 6)을 사용하면 모든 것이 처음 보입니다.스위프트 및 클래스 확장 사용

애플 문서에서는 읽을 수

". 확장은 기존의 클래스, 구조 또는 열거 형에 새로운 기능을 추가"

을 왜 내부에 직접 내 자신의 코드를 작성하지 내 자신의 수업? NSURLSession 또는 Dictionary과 같은 일부 외국 클래스의 기능을 확장하려는 경우와 달리 에 확장자를 사용하려면이 있어야합니다.

Mattt Thompson은 Alamofire 라이브러리에서 확장 기능을 사용합니다. 어쩌면 그는이 접근법을 선택한 이유에 대해 설명 할 수 없을 것입니다.

+0

선호하는 것을 사용하십시오. 그러나 확장자는 단순히 'MARK :'보다 명확하게 나타내며 시작 지점과 끝 지점을 명확하게 지정합니다. 솔직하게 말하자면, 그것은 MARK :와 확장자를 모두 사용하기 때문에 어느 쪽의 문제도 아닙니다. '확장'의 또 다른 이점은 해당 코드를 쉽게 접을 수 있다는 것입니다 (예 : '편집기'- '코드 접기 ...'- '접기'또는 음영 처리 된 왼쪽 여백에서 클릭). – Rob

답변

14

확장 프로그램을 사용하여 다른 부분의 로직을 다른 확장에 노출시킬 수 있기 때문에 완전히 합리적으로 보입니다. 이것은 또한

class ViewController: UIViewController { 
... 
} 

extension ViewController: UITableViewDelegate { 
... 
} 

extension ViewController: UITableViewDataSource { 
... 
} 

extension ViewController: UITextFieldDelegate { 
... 
} 

프로토콜 방법이 명확하게 다른 확장에 분리되어 예를 들어, 더 읽기 프로토콜 수준의 적합성을 확인하는 데 사용할 수 있습니다,이 수보다 읽기 훨씬 더 나은 것 같다 말 :

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

그래서 기존 SDK를 확장하는 것뿐만 아니라 확장 기능을 사용하여 코드를 읽기 쉽도록 만드는 것이 아무런 해가 없다고 말하고 싶습니다. 확장 기능을 사용하면 컨트롤러에 막대한 양의 코드가 생성되는 것을 피하고 쉽게 읽을 수있는 부분으로 기능을 분할 할 수 있으므로이를 사용하는 데에는 단점이 없습니다.

+0

그리고 NSCoding 프로토콜은 무엇입니까? 이 프로토콜에는 확장을 사용할 수 없습니다. – Deny

+0

이것은 까다로워지며 확장 프로그램은 지정된 이니셜 라이저를 추가 할 수 없으므로 NSCoding의'init (coder :)'는 확장을 통해 구현되지 않아야합니다. – libec

+0

확장하고있는 클래스에서 비공개로 액세스해야하는 경우 작동하지 않습니까? 또는 나는 무엇인가 놓치고 있냐? –

6

확장을 사용하면 해당 프로토콜을 구현하는 메소드 옆에 프로토콜 준수 선언을 유지할 수 있습니다.

더 확장이 없다면, 귀하의 유형을 선언 상상 :

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. 
    } 
} 
: 당신이 그것을 구현하는 구체적인 방법과 함께 프로토콜의 구현을 번들 확장을 사용하여

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 
    } 

} 

명암이

예, 프로토콜 구현을 // MARK으로 표시 할 수 있습니다 (두 기술을 결합 할 수 있음을 명심하십시오).하지만 프로토콜 지원 선언이 b e 및 파일의 본문 (구현이있는 위치).

또한 프로토콜을 구현하는 경우 구현시 남은 것이 무엇인지 알려주면서 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 
     } 
    } 
} 

따라서 동일한 확장자 내에서 두 가지를 구현해야합니다.

+1

자, 클래스 소스 코드가 몇 페이지 길어지면 클래스가 구현하는 프로토콜을 볼 수 없습니다. 코드를 통해이 정보를 검색해야합니다. 나에게 이것은 코드에서 // MARK를 사용하는 것보다 명확하지 않다. – Deny

+0

코스를위한 말,하지만 나는 의도가 명확하다는 것을 나타 내기 위해 코멘트보다는 언어를 사용한다고 말하고 싶습니다. 또한 내 편집을보고, 당신이 내 경험에 쉽게 가서 프로토콜을 구현합니다. –

+0

의견을 보내 주셔서 감사합니다. 확장을 사용하고 // MARK를 사용하여 두 접근법을 결합하려고 노력할 것입니다. – Deny