Coding Log

스위프트 찔러보기 - (6) 프로토콜과 확장(Protocols and Extensions)

본 블로그에 올라가는 포스팅은 애플의 공식 사이트를 대강 번역해서 작성하는 것이기 때문에 아래 링크에서 찔러보기 포스팅에서 쓸 예제 코드를 받을 수 있다.

참고 애플의 Playground를 이용한 Swift Example 다운로드 링크

프로토콜(Protocol)

프로토콜을 선언할 때는 protocol 키워드를 사용한다.

protocol ExampleProtocol {
    var simpleDescription: String { get }
    mutating func adjust()
}

위의 코드를 보면 프로퍼티나 메소드를 선언만 하고 구현은 안되어있는 것을 볼 수 있다.

Swift의 프로토콜은 interface 역할을 한다.

클래스, 열거형, 구조체에 프로토콜을 적용할 수 있다.

아래의 예제를 보자.

class SimpleClass: ExampleProtocol {
    var simpleDescription: String = "A very simple class."
    var anotherProperty: Int = 69105
    func adjust() {
        simpleDescription += "  Now 100% adjusted."
    }
}
var a = SimpleClass()
a.adjust()
let aDescription = a.simpleDescription
 
struct SimpleStructure: ExampleProtocol {
    var simpleDescription: String = "A simple structure"
    mutating func adjust() {
        simpleDescription += " (adjusted)"
    }
}
var b = SimpleStructure()
b.adjust()
let bDescription = b.simpleDescription

위의 예제 코드를 분석해보자.

수퍼클래스 자리에 제일 처음 작성한 프로토콜인 ExampleProtocol이 있는 것을 볼 수 있다.

ExampleProtocol에서 작성된 프로퍼티 simpleDescription를 초기화 한 후, anotherProperty 프로퍼티가 추가되었다.

마지막으로 adjust메소드의 구현부가 작성되었다.

단 SimpleStructure의 simpleDescription는 mutating 키워드가 포함된 것을 볼 수 있는 데 구조체의 프로퍼티를 수정하는 메소드를 뜻한다.

반면에 SimpleClass의 simpleDescription는 mutating 키워드가 없다.

클래스의 메소드는 클래스를 항상 수정할 수 있으므로, 따로 키워드로 표시할 필요가 없기 때문이다.

프로토콜의 제한

protocol ExampleProtocol {
    var simpleDescription: String { get }
    mutating func adjust()
}
 
let protocolValue: ExampleProtocol = a
print(protocolValue.simpleDescription)
print(protocolValue.anotherProperty)

위의 코드처럼 프로토콜은 다른 변수들을 타입 지정할때처럼 사용할 수 있다.

위의 프로토콜을 여러 클래스가 인스턴스가 사용하고 있다고 한다고 가정할때 각 인스턴스의 프로퍼티 값들은 전부 다르겠지만 프로퍼티의 이름은 동일할 것이다. 각 인스턴스들이 하나의 프로토콜을 따르고 있기 때문이다.

protocol ExampleProtocol {
    var simpleDescription: String { get }
    mutating func adjust()
}
 
class SimpleClass: ExampleProtocol {
    var simpleDescription: String = "A very simple class."
    var anotherProperty: Int = 69105
    func adjust() {
        simpleDescription += "  Now 100% adjusted."
    }
}

위의 코드는 프로토콜을 따르는 특정 인스턴스가 프로토콜에 없는 새로운 프로퍼티를 선언한 코드이다.

let protocolValue: ExampleProtocol = a
print(protocolValue.simpleDescription)
print(protocolValue.anotherProperty) // Error! 

만약 위의 protocolValue.anotherProperty 처럼 프로토콜 외부의 프로퍼티 혹은 메소드에 접근하려 하면 컴파일러가 에러를 표시한다.

즉 클래스나 구조체 등이 프로토콜을 따르듯이 프로토콜 또한 클래스나 구조체에서 추가 구현된 메소드나 프로퍼티에 접근할 수 없다는 뜻이다.

확장(Extension)

extension 키워드를 사용하여 기존의 메소드나 계산된 프로퍼티등에 새로운 기능을 추가할 수 있다.

extension을 사용하면 다른 곳에서 선언된 타입, 라이브러리와 프레임워크에서 불러온 타입에도 프로토콜을 적용할 수 있다.

extension Int: ExampleProtocol {
    var simpleDescription: String {
        return "The number \(self)"
    }
    mutating func adjust() {
        self += 42
    }
}
print(7.simpleDescription)

위의 코드는 기존에 정의된 Int 타입에 ExampleProtocol을 추가하여 기능을 확장하는 예제 코드이다.

DISQUS 로드 중…
댓글 로드 중…

트랙백을 확인할 수 있습니다

URL을 배껴둬서 트랙백을 보낼 수 있습니다