Protocols 정리본 (2) - 요구사항을 정의하는 방법

YeongHyeon Jo·2024년 2월 22일
0

Swift

목록 보기
5/6

프로토콜에 대해 기본적인 개념을 파악했다면 이를 정의하는 방법은 어떻게 되는지 알아보려고한다.

1. 속성의 요구사항을 정의

  • 속성의 뜻에서 var로 선언 (let으로는 선언할 수 없다.)
  • get, set 키워드를 통해서 읽기/쓰기 여부를 설정할 수 있다. (이는 최소한의 요구사항이다.)
  • 저장 속성/계산 속성으로 모두 구현이 가능하다.
protocol RemoteMouse {
    var id: String { get }
    var name: String { get set }
    static var type: String { get set }
	class var type: String { get set }
}

var 저장 속성을 가지며, { get }{ get set } 으로 각각 읽기, 읽기/쓰기 용도로 구현할 수 있다.
해당 조건으로 프로토콜을 채택하게되면 아래와 같은 코드가 된다.

struct SamSungTV: RemoteMouse {
    var id: String = "1"
    var name: String = "Samsung TV"
    static var type: String = "리모콘"
}

struct LGTV: RemoteMouse {
    let id: String = "1"
    var name: String = "LG TV"
    static var type: String = "리모콘"
}

실제로 위에서 { get } 으로 선언 되어있는 경우, TV 구조체의 속성 id를 저장속성으로 구현할 경우 let으로도 구현할 수 있다.
하지만 속성 name의 경우에는 { get set } 으로 선언되어 있어, 오로지 var 변수 저장 속성만이 가능하다.
계산 속성으로 구현할 경우에는 { get } 으로 선언한 경우에는 getter만 만들거나, getter setter 모두를 생성할 수 있다.
하지만, { get set } 으로 선언된 경우에는 getter setter 모두 제공해야한다.

struct SamSungTV: RemoteMouse {
    var id: String {
    	get {
        	return "1"
        }
    }
    var name: String = "Samsung TV"
    static var type: String = "리모콘"
}

struct LGTV: RemoteMouse {
    var id: String {
    	get {
        	return "1"
        }
        set {
        	self.name = newValue
        }
    }
    var name: String = "LG TV"
    static var type: String = "리모콘"
}

struct AppleTV: RemoteMouse {
    var id: String = "1"
    var name: String {
    	get {
        	return "Apple TV"
        }
        set {
        	self.id = newValue
        }
    }
    static var type: String = "리모콘"
}

*타입(static) 속성 요구사항

  • 이는 채택할 경우 저장 타입 속성(static var)과 계산 타입 속성(class var)로 모두 구현이 가능하다.
  • 저장 타입 속성의 경우에는 재정의가 불가능하지만, 계산 타입 속성의 경우에는 재정의가 가능하다.
// 1) 저장 타입 속성으로 구현
class SmartPhone: RemoteMouse {
    var id: String {
        return "777"
    }
    var name: String {
        get { "아이폰" }
        set { }
    }
    static var type: String = "리모콘"     // 타입 저장 속성은 (상속은 되지만) 재정의 원칙적 불가능
}

// 2) 계산 타입 속성으로 구현
class Ipad: RemoteMouse {
    var id: String = "777"
    var name: String = "아이패드"
    class var type: String {       // 타입 계산 속성은 재정의 가능 (class키워드 가능)
        get { "리모콘" }
        set { }
    }
}

2. 메서드의 요구사항을 정의

  • 메서드의 헤드부분(인풋/아웃풋)의 형태만 요구사항으로 정의
  • mutating 키워드: (구조체로 제한하는 것은 아님) 구조체에서 저장 속성 변경하는 경우, 구조체도 채택 가능하도록 허락하는 키워드
  • 타입 메서드로 제한 하려면, static키워드만 붙이면 됨
    (채택해서 구현하는 쪽에서 static / class 키워드 모두 사용 가능)
// 1) 정의
protocol RandomNumber {
    static func reset() 
    func random() -> Int
}


// 2) 채택 / 3) 구현
class Number: RandomNumber {
    static func reset() {
        print("다시 셋팅")
    }
    func random() -> Int {
        return Int.random(in: 1...100)
    }
}

구조체의 경우 메서드 내에서 저장 속성의 값을 변경해야할 경우, mutating 을 선언해주어야한다. 이때, 프로토콜에 선언을 하고 구조체에서 채택할 경우 구조체 내에 함수내에도 mutating 가 선언되어야한다. 하지만 클래스의 경우에는 해당 키워드가 필요없으니 빼고 선언을 하면된다.

protocol Rename {
    mutating func changeName(newName: String)
}
 
struct Name1: Rename {
    var name: String = "Potter"
    
    mutating func changeName(newName: String) {
        self.name = newName
    }
}
 
class Name2: Rename {
    var name: String = "JiSung"
    
    func changeName(newName: String) {
        self.name = newName
    }
}

실제로 실행할 경우 두 개의 모두의 저장 속성의 값이 변경되었다.

프로토콜의 내용이 너무 많고도 많지만 실제로 프로젝트에서도 적용해보고 사용하면서 내용을 새로 작성해보도록해봐야겠다!

profile
my name is hyeon

0개의 댓글