조앤의 기술블로그

[Swift] Protocol (프로토콜) #1 본문

Study/Swift

[Swift] Protocol (프로토콜) #1

쬬앤 2020. 3. 4. 12:25

프로토콜(Protocol)은 메소드, 속성에 대한 청사진이고, 다른 특정 기능에 대한 요구사항을 정의합니다. 

프로토콜은 클래스나 구조체가 어떤 기준을 만족하거나 또는 특수한 목적을 달성하기 위해 구현해야 하는 메소드와 프로퍼티의 목록입니다.

 

프로토콜의 역할은 특정 기능이나 속성에 대한 설계도입니다. 

프로토콜은 구체적인 내용이 없는 프로퍼티나 메소드의 단순한 선언 형태로 구성되며, 구체적인 내용은 이 프로토콜을 채용하는 객체에서 담당합니다. 프로토콜에서 중요한 것은 형식입니다. 

 

프로토콜은 클래스, 구조체, 열거형에 채용(conform)될 수 있고, 이들이 실제 구현을 담당합니다. 

프로토콜의 요구사항을 만족시키는 형식을 프로토콜을 채용(conform)한다. 라고 표현합니다. 

 

특정 형식이 구현해야만 하는 요구사항을 특정하고 싶을 때, 프로토콜을 확장할 수 있습니다. 

 

[Protocol Syntax]

protocol SomeProtocol {
	//protocol definition
}
struct SomtStructure: FirstProtocol, AnotherProtocol {
	//structure definition
}

class SomeClass: SomeSuperClass, FirstProtocol, AnotherProtocol {
	//class definition
}

프로토콜은 다중 상속을 허용하므로 1개 이상의 프로토콜을 채용할 수 있습니다. 

클래스에서 프로토콜을 채용할 때, super class의 이름을 먼저 써주어야 합니다. 

 

[Property Requirements]

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

var 키워드로 속성이라는 것을 나타내고 가변성은 get set 키워드로 정의합니다. 

get이 만족해야 하는 최소 요구사항이 됩니다.

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

타입 프로퍼티를 선언할 때에는 앞에 static 키워드를 붙여주면 됩니다. 

 

-예제-

protocol FullyNamed {
	var fullName: String { get }
}

fullName 속성을 읽기 전용으로 선언하였습니다. 

struct Person: FullyNamed {
	var fullName: String
}
let jin = Person(fullName: "Kim Seok-jin")
//jin.fullName is "Kim Seok-jin"

FullyNamed 프로토콜을 채용하는 구조체 Person입니다. 

class Starship: FullyNamed {
	var prefix: String?
    var name: String
    init(name: String, prefix: String? = nil) {
    	self.name = name
        self.prefix = prefix
    }
    var fullName: String {
    	return (prefix != nil ? prefix + " " : "") + name
    }
}
var ncc1701 = Starship(name: "Enterprise", prefix: "USS")
// ncc1701.fullName is "USS Enterprise"

get이 만족해야 하는 최소 요구사항이 되므로 get set을 만족해도 요구사항을 만족하게 됩니다. 

 

 

[Method Requirements]

protocol SomeProtocol {
	static func someTypeMethod()
}

type method를 선언할 때는 func 앞에 static 키워드를 붙여줍니다. 

protocol RandomNumberGenerator {
	func random() -> Double 
}

함수를 선언하고, 리턴형도 선언해 주었습니다. 

 

[Mutating Method Requirements]

protocol Toggable {
	mutating func toggle()
}

값 형식에서 값을 바꾸는 함수를 선언할 때 mutating 키워드를 씁니다. 

 

enum OnOffSwitch: Toggable {
	case off, on
    mutating func toggle() {
    	switch self {
        case .off:
        	self = .on
        case .on:
        	self = .off
        }
    }
}
var lightSwitch = OnOffSwitch.off
lightSwitch.toggle()
// lightSwitch is now equal to .on

Toggable 프로토콜의 형식에 따라 함수 앞에 mutating 키워드를 붙여줍니다. 

 

[Initializer Requirements]

protocol SomeProtocol {
	init(someParameter: Int)
}

프로토콜에서 특정 생성자를 선언할 수 있습니다. 바디는 생략하고 선언만 합니다. 

 

- class Implementations of Protocol Initializer Requirements

class SomeClass: SomeProtocol {
	required init(someParameter: Int){
    	// initializer implementation
    }
}

클래스에서 채용한 프로토콜의 생성자를 사용할 때는 required 키워드를 붙여주어야 합니다.

(required 키워드는 SomeClass를 상속하는 subclass에서도 해당 생성자를 선언하도록 강제합니다.)

 

protocol SomeProtocol {
	init()
}

class SomeSuperClass {
	init() {
    	//initializer implementation
    }
}

class SomeSubClass: SomeSuperClass, SomeProtocol {
	// "required" from SomeProtocol conformance, "override" from SomeSuperClass
    required override init() {
    	//initializer implementation
    }
}

프로토콜과 슈퍼클래스에서 같은 형식의 생성자를 채용한다면 'required override init()....'의 형식으로 구현해줍니다. 

 

 

 

 

 

 

참고: KxCoding.com - Mastering Swift 강의 (링크), 꼼꼼한 재은씨 'Swift 문법편', Swift 공식 홈페이지(링크)

'Study > Swift' 카테고리의 다른 글

[Swift] Generics (제네릭)  (0) 2020.03.09
[Swift] Extension (익스텐션)  (0) 2020.02.27
[Swift] Initializers #2  (0) 2020.02.26
[Swift] Initializers #1  (0) 2020.02.26
[Swift] Type Casting (타입 캐스팅)  (0) 2020.02.25