Notice
Recent Posts
Recent Comments
Link
大器晩成
[Protocols] 프로토콜 요구사항 본문
프로토콜 속성의 요구사항
- 프로토콜에 선언되는 프로퍼티에는 초기값을 할당할 수 없다.
- var로만 가능합니다. (let으로 선언 불가능)
-> 개인적인 생각 ) 프로토콜은 선언만 할 뿐 값을 지정할 수 없기 때문에, let키워드를 사용하지 못하는 거 같다. let 초기값을 지정해야 하지만, var는 지정하지 않아도 되기 때문에, 프로토콜의 성격을 봤을 때 var 키워드만 사용하는 것이 많은 거 같다.
또, 프로토콜에서는 함수를 정의할 때, private 키워드를 사용할 수 없고, 채택한 클래스나, 구조체에서 함수를 사용할 때에도 private 키워드를 사용할 수 없다. 이 또한 프로토콜의 성격과 맞지 않기 때문에 사용이 불가능한 거 같다. 프로토콜은 어느 곳에든지 채택만 하면 사용을 할 수 있어야 하는데, private은 해당 클래스나, 구조체 내에서만 사용이 가능하도록 하는 키워드이기 때문에, 둘의 성격은 맞지 않기 때문에, private 키워드를 프로토콜에서는 쓸 수 없는 거 같다. - get, set 키워드를 통해 읽기/쓰기 여부를 설정 (최소한의 요구사항으로, 연산/저장속성을 구분하지 않는다.)
- 프로퍼티의 종류, 이름, 변수 구분, 타입, 읽기 전용인지 등에 대한 정의만 할 뿐이다.
protocol SomePropertyProtocol {
var name: String { get } // ===> let 저장속성 / var 저장속성 / 읽기계산속성 / 읽기,쓰기 계산속성
var description: String { get set } // ==> var 저장곡성 / 읽기, 쓰기 계산속성
static var type: String {get set } // ==> 타입 저장속성 (static)
// ==> 타입 계산속성 (class)
}
struct person: SomePropertyProtocol {
var name = "Zerobug"
var description: String {
get {
return "Hello \(name)"
} set {
name = newValue
}
}
static var type: String = "사람"
}
var zerobug = person()
zerobug.description
zerobug.name
zerobug.description = "00"
zerobug.description
person.type
타입속성
1. 저장 타입 속성으로 구현
protocol SomePropertyProtocol {
var name: String { get }
var description: String { get set }
static var type: String { get set }
}
class Undergraduate: SomePropertyProtocol {
var name: String {
return "Zerobug"
}
var description: String {
get { "대학생입니다" }
set { }
}
static var type: String = "사람" // 타입 저장 속성은 (상속은 되지만) 재정의 원칙적 불가능
}
- 저장속성은 원칙적으로 재정의가 불가능하기 때문에, class 키워드를 사용할 수 없습니다.
2. 계산 타입 속성으로 구현
class GradStudent: SomePropertyProtocol {
var name: String {
return "Zerobug"
}
var description: String {
get { "대학원생입니다" }
set { }
}
class var type: String { // 타입 계산 속성은 재정의 가능 (class키워드 가능)
get { "노예" }
set { }
}
}
- 계산 속성은 메서드이기 때문에, 하위 타입에서 재정의 가능합니다.
- class키워드를 사용할 경우 하위 클래스에서 재정의가 가능합니다.
- 재정의를 원치 않을 경우 class키워드가 아닌 static 키워드를 사용하면 됩니다.
프로토콜 메서드의 요구사항
- 메서드의 헤드 부분(인풋/아웃풋)의 형태만 요구사항으로 정의합니다.
-> 메서드의 이름, 파라미터 타입, 파라미터 이름, 반환 타입까지 정의합니다. - mutating 키워드: 구조체에서 저장 속성을 변경하는 경우, 구조체도 채택 가능하도록 허락하는 키워드입니다.
- 타입 메서드로 제한하려면, static 키워드만 붙이면 됩니다.
(채택해서 구현하는 쪽에서 static / class 모두 사용이 가능합니다.)
protocol SomeMethodProtocol {
func execute(cmd: String)
func showPort(p: Int) -> String
}
struct RubyService: SomeMethodProtocol {
func execute(cmd: String) {
if cmd == "start" {
print("실행합니다.")
}
}
func showPort(p: Int) -> String {
return "Port: \(p)"
}
}
프로토콜 메서드 정의 방법
protocol NewMethodProtocol {
mutating func execute (cmd command: String, desc: String)
func showPort(p: Int, memo desc: String) -> String
}
struct RubyNewService: NewMethodProtocol {
func execute(cmd command: String, desc: String) {
if command == "start" {
print("\(desc)를 실행합니다.")
}
}
func showPort(p: Int, memo desc: String) -> String {
return "Port: \(p), Memo: \(desc)"
}
}
struct RubyNewService2: NewMethodProtocol {
func execute(cmd comm: String, desc d: String) { //내부매개변수명 변경
if comm == "start" {
print("\(d)를 실행합니다.")
}
}
func showPort(p: Int, memo description: String) -> String { //내부매개변수명 변경
return "Port: \(p), Memo: \(description)"
}
}
- 외부 매개변수명은 프로토콜을 그대로 따라야 하지만, 내부 매개변수명은 임의로 바꾸어 사용이 가능합니다.
- 만약 내부 매개변수명과 외부 매개변수명이 프로토콜에서 통합되어 선언되어 있을 경우 채택하는 곳에서, 이를 분리하여 내부 매개변수명과 외부 매개변수명으로 따로 작성해도 됩니다.
mutating 키워드
protocol SomePropertyProtocol {
func doSomething()
}
class mutatingTest: SomePropertyProtocol {
var name = "Park"
func doSomething() {
self.name = "Zerobug"
}
}
protocol SomePropertyProtocol2 {
mutating func doSomething()
}
struct mutatingTest2: SomePropertyProtocol2 {
var name = "Park"
mutating func doSomething() {
self.name = "Zerobug"
}
}
- 클래스 내 메서드의 저장속성을 변경은 가능합니다. 하지만 구조체에서는 변경이 불가능하기 때문에, mutating키워드를 사용하여 구조체 내 메서드에서 저장속성의 값을 변경이 가능하도록 해줍니다. 이때, 프로토콜에서도 mutating 키워드를 사용해서 함수의 헤더를 작성해야 합니다.
열거형에서 mutating
protocol Togglable {
mutating func toggle() // mutating의 키워드는 메서드 내에서 속성 변경의 의미일뿐(클래스에서 사용 가능)
}
enum OnOffSwitch: Togglable {
case on
case off
mutating func toggle() {
switch self { // self는 .on .off
case .off:
self = .on
case .on:
self = .off
}
}
}
var s = OnOffSwitch.off
s.toggle()
s.toggle()
- 열거형도 구조체와 마찬가지로 값 타입이기 때문에 mutating 키워드를 사용해야 합니다.
클래스의 경우
class BigSwitch: Togglable {
var isOn = false
func toggle() { // mutating 키워드 필요없음 (클래스 이기 때문)
isOn = isOn ? false : true
}
}
var big = BigSwitch()
print(big.isOn) //false
big.toggle()
print(big.isOn) //true
728x90
'iOS > Swift 문법' 카테고리의 다른 글
[프로토콜] - 서브스크립트 (0) | 2025.02.06 |
---|---|
[Protocols] 생성자 (0) | 2025.01.23 |
[Protocols] 프로토콜(Protocol) (0) | 2025.01.09 |
[Extensions] 멤버의 확장(중첩타입, Nested Types) (0) | 2025.01.07 |
[Extensions] 멤버의 확장(서브 스크립트) (0) | 2025.01.05 |