프로토콜(Protocol)의 메서드(Method) 정의

썹스·2022년 10월 27일
0

Swift 문법

목록 보기
26/68

프로토콜(Protocol)의 메서드(Method) 정의

  • 프로토콜에서 정의 가능한 메서드의 종류와 형태는 다양합니다. (인스턴스 메서드, 생성자, 서브 스크립트 등... / 파라미터의 유무, 리턴형의 유무 등...)

  • 메서드의 종류와 형태에 따라 프로토콜에서 정의하는 방법이 다르며, 채택(Adopt) 후 사용하는 방법과 기능이 조금씩 다를 수 있습니다.


📌 1. 프로토콜의 인스턴스 메서드(Instance Method) 정의

✅ 일반적인 인스턴스 메서드(Instance Method) 정의

  • 일반적인 인스턴스 메서드를 정의할 때는 "메서드명", "리턴(반환) 타입", "파라미터명", "파라미터 타입"만을 작성합니다.
  • 메서드의 기능은 구현하지 않습니다. 즉, 중괄호 { } 을 작성하지 않습니다.
protocol ProtocolMethod{
    func test1()    // 프로토콜 + 리턴값이 없는 경우
   
    func test2() -> String    // 프로토콜 없이 값만 리턴하는 경우
  
    func test3(x: String) -> String    // 프로토콜을 받아 값을 리턴하는 경우
}


class kim: ProtocolMethod{
    func test1() {
        print("프로토콜 + 리턴값이 없는 경우")
    }
   
    func test2() -> String {
        return "프로토콜 없이 값을 리턴하는 경우"
    }
  
    func test3(x: String) -> String {
        return "\(x) 프로토콜을 받아 값을 리턴하는 경우"
    }
}

✅ "mutating" 키워드가 들어간 인스턴스 메서드(Instance Method) 정의

  • 클래스는 함수(메서드)를 사용하여 저장 속성의 값을 변경할 때는 큰 문제가 없습니다. (데이터를 메모리의 힙 영역에 저장하기 때문 = Reference Type)
  • 구조체는 함수(메서드)를 사용하여 저장 속성의 값을 변경하는 것이 불가능합니다. 때문에 mutating 키워드를 사용해야 합니다. (데이터를 메모리의 스택 영역에 저장하기 때문 = Value Type)
  • 프로토콜에서 "mutating" 키워드가 들어간 메서드가 정의되었을 때, 클래스는 해당 키워드를 생략할 수 있습니다. (잘 생각해보면... 당연한...)
protocol ProtocolMethod{
    mutating func test1(x: Int)
}


class kim: ProtocolMethod{
    var a: Int = 0

    func test1(x: Int) {   // 클래스는 mutating 키워드 없이 작동
        self.a = x
    }
}


struct lee: ProtocolMethod{
    var a: Int = 0
   
    mutating func test1(x: Int) {   // 구조체는 mutating 키워드 사용!
        self.a = x
    }
}

📌 2. 프로토콜의 타입 메서드(Type Method) 정의

✅ 타입 메서드(Type Method) 정의

  • 프로토콜에서 타입 메서드를 정의할 때는 "static" 사용해야 합니다. ("class" 키워드 사용 X)

  • "static" 키워드로 선언했지만, 사용 시 상황에 따라 "static" 또는 "class"로 사용이 가능합니다.
protocol ProtocolMethod{
    static func test1()
  
    static func test2() -> String
  
    static func test3(x: String) -> String
}


class kim: ProtocolMethod{
    static func test1() {
        print("프로토콜 + 리턴값이 없는 경우")
    }
  
    class func test2() -> String {  // static 키워드로 정의했지만, class 타입으로 사용 가능!
        return "프로토콜 없이 값을 리턴하는 경우"
    }
  
    static func test3(x: String) -> String {
        return "\(x) 프로토콜을 받아 값을 리턴하는 경우"
    }
}

📌 3. 프로토콜의 생성자(Initializer) 정의

✅ 지정 생성자(Designated Initializer) 정의

  • 클래스는 지정 생성자가 정의된 프로토콜을 채택하여 사용할 때는 필수 생성자(Required Initializer)로 정의하여 사용해야 합니다. (프로토콜의 요구사항은 필수이기 때문)
  • 구조체는 필수 생성자가 없기 때문(구조체는 상속 기능이 없기때문)에 일반적인 지정 생성자로 정의하여 사용할 수 있습니다.
protocol ProtocolMethod{
    init(x: Int)
}


class kim: ProtocolMethod{
    //클래스는 생성자 기능이 있는 프로토콜을 채택할 때 필수 생성자로 정의하여 사용해야 합니다.
    required init(x: Int){
        //code
    }
}


struct lee: ProtocolMethod{
    init(x: Int) {
        //code
    }
}

✅ 편의 생성자(Convenience Initializer)

  • 프로토콜에서 편의 생성자를 정의하는 것은 불가능합니다.
    🚨 Convenience initializer not allowed in non-class type 'ProtocolMethod'

✅ 필수 생성자(Required Initializer)

  • 프로토콜에서 필수 생성자를 정의하는 것은 불가능합니다.
    🚨 'required' initializer in non-class type 'ProtocolMethod'

✅ 실패가능 생성자(Failable Initializer)

  • 클래스 또는 구조체는 실패가능 생성자가 정의된 프로토콜을 채택하여 사용할 때 지정 생성자 또는 실패가능 생성자로 정의하여 사용할 수 있습니다. (옵셔널 타입이 일반 타입보다 큰 개념이기 때문에 가능)
protocol ProtocolMethod{
   init?(x: Int)
}


class kim1: ProtocolMethod{
    required init?(x: Int){    // ? / ! 둘 다 가능
        //code
    }
}
class kim2: ProtocolMethod{
    required init(x: Int){
        //code
    }
}


struct lee1: ProtocolMethod{
    init!(x: Int) {            // ? / ! 둘 다 가능
        //code
    }
}
struct lee2: ProtocolMethod{
    init(x: Int) {
        //code
    }
}

📌 4. 프로토콜의 서브스크립트(Subscripts) 정의

프로토콜에서 서브스크립트를 정의할 때는 get만을 사용하여 읽기 전용(read only)으로 정의하여 사용하거나 get과 set을 둘 다 사용하여 읽기/쓰기(read/write)용으로 정의해야 합니다.

✅ 서브스크립트(Subscripts) 정의

  • 프로토콜에서 서브스크립트를 get(읽기) 전용으로 정의하여 사용할 때 get(읽기) 또는 get/set(읽기/쓰기)으로 정의할 수 있습니다.
  • 프로토콜에서 서브스크립트를 get/set(읽기/쓰기)용으로 정의하여 사용할 때 get/set(읽기/쓰기)으로만 정의할 수 있습니다.
protocol ProtocolMethod1{
    subscript (index1: Int) -> Int{ get }
}

protocol ProtocolMethod2{
    subscript (index2: Int) -> Int{ get set }
}


class kim: ProtocolMethod1{
    var arrNum = [1,2,3,4,5]
   
    subscript(index1: Int) -> Int {
        get{
            return arrNum[index1]
        }
        set{  //set(쓰기) 생략 가능
            arrNum[index1] = newValue
        }
    }
}


class lee: ProtocolMethod2{
    var arrNum = [1,2,3,4,5]
   
    subscript(index2: Int) -> Int {
        get{
            return arrNum[index2]
        }
        set{  //set(쓰기) 생략 불가능, 필수 작성
            arrNum[index2] = newValue
        }
    }
}


Reference

참고자료: 앨런 Swift문법 마스터 스쿨

profile
응애 나 코린이(비트코인X 코딩O)

0개의 댓글