[Swift] Protocols, Extensions

Lena·2020년 12월 9일
0
post-custom-banner

Protocols

Protocol은 메서드, 프로퍼티 등 필요한 기능의 최소 규칙(blueprint)을 정의한다. 그리고 class, struct, enum에 의해 채택(adopted)되어 그 요구사항이 구현된다. 프로토콜의 요구사항을 충족시킨 타입을 프로토콜을 준수(conform)했다라고 한다.
프로토콜에 요구사항을 추가하거나 추가적인 기능을 구현하기 위해 프로토콜을 extend 할 수 있다.

Protocol Syntax

프로토콜은 여러 개 채택할 수 있다. 만약 클래스를 상속한다면 채택할 프로토콜 앞에 상속할 클래스를 명시해야 한다.

protocol SomeProtocol {
    // protocol definition goes here
}

class SomeClass: SomeSuperclass, FirstProtocol, AnotherProtocol {
    // class definition goes here
}

Property Requirements

프로토콜은 instance 또는 type property를 요구할 수 있다. property name, type, gettable, settable만을 명시하며, 항상 var로 선언한다.

protocol SomeProtocol {
    var mustBeSettable: Int { get set }
    var doesNotNeedToBeSettable: Int { get }
}

그러므로 프로퍼티 요구를 준수할 때, gettable and settable 프로퍼티는 let이 될 수 없고, read-only도 될 수 없다.

Always prefix type property requirements with the static keyword when you define them in a protocol. This rule pertains even though type property requirements can be prefixed with the class or static keyword when implemented by a class:

타입 프로퍼티 요구는 항상 static 키워드만을 사용한다.

protocol AnotherProtocol {
    static var someTypeProperty: Int { get set }
}

프로토콜은 stored property 또는 computed property를 구분해서 명시하지 않는다. 프로퍼티 요구를 준수할 때 원하는대로 해석할 수 있다.

Method Requirements

프로토콜은 instance 또는 type method를 요구할 수 있다. method를 정의할 때 curly braces {} 와 method body는 작성하지 않는다.
파라미터의 기본값도 작성하지 않는다.

Variadic parameters are allowed, subject to the same rules as for normal methods. Default values, however, can’t be specified for method parameters within a protocol’s definition.

Mutating Method Requirements

프로토콜의 메서드가 자신이 속한 value type의 인스턴스 값을 변경해야 하는 경우, mutating 키워드를 붙여주어야 한다.

protocol Togglable {
    mutating func toggle()
}

Protocols as Types

프로토콜도 하나의 data type이다.

Delegation💡

Delegation은 인스턴스의 책임을 넘기는(Delegation) 디자인 패턴 중 하나로, protocol에 의해 구현된다.

// View
class UITableView : UIScrollView {
    weak var delegate: UITableViewDelegate?
}

// Controller
class UIViewController: UITableViewDelegate {
    let tableView = UITableView()
    
    override func viewDidLoad() {
        tableView.delegate = self
    }
    
    // method implement...
}
  1. (delegate)프로토콜이 이미 정의되어 있다.
  2. 뷰의 대리자를 위임한다.
    view.delegate = self
  3. 대리자는 프로토콜을 채택한다.
  4. 필수 메서드를 구현한다.
  5. 선택 메서드는 필요에 따라 구현한다.

Class-Only Protocols

AnyObject를 상속해서 채택 가능한 타입을 class로 제한할 수 있다.

protocol SomeClassOnlyProtocol: AnyObject, SomeInheritedProtocol {
    // class-only protocol definition goes here
}

Optional Protocol Requirements

프로토콜을 선언하면서 선택적 요구사항을 정의할 수도 있다.
선택적 요구사항을 정의한 프로토콜은 @objc 붙이며, @objc protocol은 class 타입에 의해서만 채택될 수 있다.

@objc protocol CounterDataSource {
    @objc optional func increment(forCount count: Int) -> Int
    @objc optional var fixedIncrement: Int { get }
}

Extensions

Extensions은 class, struct, enum 또는 protocol에 기능을 추가하는 것이다.

Extension Syntax

extension 키워드를 사용해 선언한다.

extension SomeType {
    // new functionality to add to SomeType goes here
}

extension을 통해서 더 많은 프로토콜을 채택할 수 있다.

extension SomeType: SomeProtocol, AnotherProtocol {
    // implementation of protocol requirements goes here
}

Computed Properties

Extensions can add computed instance properties and computed type properties to existing types.

// extension으로 코드를 깔끔하게
// self가 navigation controller라면, navigation 되어 보여지는 view를 리턴
extension UIViewController {
    var contents: UIViewController {
        if let navcon = self as? UINavigationController {
            return navcon.visibleViewController ?? self
        } else {
            return self
        }
    }
}
// Extension.swift

extension UIView {
    public var width: CGFloat {
        return frame.size.width
    }
    
    public var height: CGFloat {
        return frame.size.height
    }
    
    public var top: CGFloat {
        return frame.origin.y
    }
    
    public var bottom: CGFloat {
        return frame.origin.y + frame.size.height
    }
    
    public var left: CGFloat {
        return frame.origin.x
    }
    
    public var right: CGFloat {
        return frame.origin.x + frame.size.width
    }
}

References

https://docs.swift.org/swift-book/LanguageGuide/Protocols.html
https://docs.swift.org/swift-book/LanguageGuide/Extensions.html

post-custom-banner

0개의 댓글