APPLE/Swift 문법

[ 기초 문법 ] Protocol

pandada 2022. 8. 19. 22:57
반응형

이번에는 Protocol에 대해서 알아보려고 한다.

 

Protocol

  • 특정 역할을 하기 위한 메소드, 프로퍼티, 기타 요구사항 등의 청사진을 정의
  • 구조체, 클래스, 열거형은 프로토콜을 채택해서 기능을 실행하기 위한 프로토콜의 요구사항을 실제로 구현할 수 있다.
  • 프로토콜이 요구하는 사항을 모두 충족하면 해당 타입이 채택한 프로토콜을 준수할 수 있다고 할 수 있다.

 

대략적으로 정리를 하면 프로토콜은 일종의 규약이다. 즉 해당 규약을 지켜야 한다고 생각하면 된다.

예를들어 인터넷 통신 프로토콜인 TCP/IP인 경우에 인터넷 통신을 할 수 있도록 지켜야하는 규약인 것처럼 해당 프로토콜을 채택하려면 프로토콜의 내용을 지켜야 한다는 내용으로 이해하면 될 것 같다.

 

그럼 이제 protocol의 사용 방법에 대해서 알아보자.

 

protocol 이름 {
    프로토콜의 요구사항
}

 

프로토콜은 클래스와 구조체의 선언과 비슷하게 앞부분만 protocol 로 작성을 하고, 이후 코드 블럭에 요구사항에 대해서 작성하면 된다.

 

< SampleProtocol 선언 및 채택 >

 

좌측의 이미지는 SampleProtocol 에 대한 내용을 정의했다. 사용 방법을 위에서 언급한 대로 우선은 아무것도 없는 빈 내용의 Protocol을 정의했다.

이후에 우측의 이미지는 Class와 Struct를 선언했고, 이후에 SampleProtocol을 채택 시킨 내용이다.

현재는 프로토콜의 내용이 비어있는 부분이지만, 이후에는 추가를 진행해서 테스트를 진행해 볼 부분이니 사용법을 한번 코드로 표현해봤다.

 

protocol의 경우에는 2개 이상의 protocol도 채택을 하게 할 수 있다.

 

< 2개의 protocol 채택 >

좌측의 이미지에서 SampleStruct2라는 추가 구조체를 만들었고, SampleProtocol과 SampleProtocol2에 대한 protocol을 2개다 채택시켰다.

이렇게 여러개의 protocol을 채택하려고 하려면 , (쉼표)를 활용하여 열거해주면 된다.

 

우측의 이미지는 상속받은 서브 클래스에 프로토콜을 채택시켜본 내용이다.

우측의 이미지에 대해서 얘기를 해보면 Upclass 라는 부모 클래스를 생성하였고, 이 부모 클래스를 상속받는 DownClass에 대해서 작성을 했다. 

참고로 클래스의 경우에 상속과 프로토콜 채택을 둘다 작성을 하려면 반드시 상속받는 클래스를 먼저 작성해줘야한다.

 

class class명 : 상속받을 Class, protocol 이름 , protocol 이름 ...

 

이렇게 : 이후에는 반드시 상속받을 Class를 먼저 선언해줘야한다.

 

자 그럼 이번에는 프로토콜 내부의 코드블럭에 내용을 작성하여 내용을 확인해보도록 하자.

우선적으로 protocol 중에서 프로퍼티 protocol에 대해서 확인을 해보도록 하자.

 

< protocol 코드 블럭 작성>

프로퍼티의 요구사항을 맞추기 위해서 SampleProtocol의 내용에 Int 타입인 name과 age 프로퍼티를 선언하였다.

protocol은 자신을 채택한 타입이 어떤 프로퍼티를 구현해야하는지 요구할 수 있다.

protocol이 프로퍼티에 준수하도록하고, 준수할 때에 저장 프로퍼티인지 연산 프로퍼티인지 지정하지 않고, 프로퍼티 이름과 타입만 지정하면 된다.

 

이때 프로퍼티에 읽기만 가능한 프로퍼티인지 읽기/쓰기가 둘다 가능한 프로퍼티인지 get과 set을 이용해 지정해줘야한다.

위의 이미지를 확인해보면 name은 읽기/쓰기가 둘다 가능하고, age는 읽기만 가능하다는 것을 알 수 있다.

 

또한 프로퍼티를 요구할 때에는 항상 var로 작성을 해야한다.

그럼 이제 SampleProtocol을 채택하고 있는 struct를 생성해보자.

 

< does not conform to protocol ...  >

좌측의 이미지인 경우 protocol의 코드블럭 안에 프로퍼티 변수에 대한 요구사항을 정의하였지만, protocol을 채택한 SampleStruct 구조체에 프로퍼티에 대한 내용을 정의하지 않아서 에러가 발생했다.

이렇게 protocol에 정의한 내용을 수용하지 않으면, 에러가 발생하게 된다.

 

우측의 이미지처럼 protocol상에서 정의한 프로퍼티의 내용을 작성하였다.

이때에 에러가 발생하지 않은 것을 확인할 수 있다.

 

이렇게 요구사항 프로퍼티는 해당 protocol을 채택하는 구조체, 열거형, 클래스에 해당 프로퍼티를 무조건 사용하라는 식의 규약을 제시하는 부분이다.

 

 

그럼 이제 메소드에 대한 요구사항을 정의해보도록 하자.

 

< 메소드 요구사항 >

좌측의 이미지 경우에는 기존의 SampleProtocol에 메소드를 선언하였다. 이후에 SampleStruct 구조체에서는 역시 위에서 확인했다 싶이 동일한 에러가 발생한다.

기존의 SampleProtocol에는 printSampleProtocol()이라는 함수 메소드가 있는데 왜 규약을 지키지 않았느냐. 하는 내용이다.

 

우측의 이미지인 경우에 따라서 SampleProtocol에서 정의하고 있는 printSampleProtocol이라는 메소드를 구조체 안에 작성하였고, 해당 함수의 코드블럭에 print("함수 내용") 이라는 출력 내용을 작성하였다.

 

이처럼 프로퍼티 요구사항과 마찬가지로 메소드 자체도 요구를 할 수 있다. 이때에 요구하는 메소드는 인스턴스 / 타입 메소드 모두 가능하다.

이렇게 작성을 하면 불필요한 코드 내용을 피하게 하고, 만들라고 하는건 만들도록 지시를 할 수 있다고 생각하면 된다.

 

protocol의 생성자 관련된 내용도 한번 확인해보도록 하자.

 

< protocol 이니셜라이저 >

이렇게 protocol에 요구하는 생성자를 선언할 수 있다.

이때에 protocol 내부의 init 내용에는 몸통 부분의 코드블럭은 작성을 하지 않아도 되며, 생성자 키워드와 매개변수만을 정해주면 된다.

 

< SampleCalss 에러 >

좌측의 이미지대로 확인을 해보면 SampleProtocol2에서는 init 내용을 작성하였지만, 윗 부분에서 계속 했던 내용과 동일하게 SampleClass에는 init의 내용을 정의하지 않아 에러가 발생했다.

 

우측의 이미지인 경우에 SampleProtocol2의 init 내용을 충족했고, age라는 변수의 초기화를 진행해준 내용이다.

따라서 에러가 사라진 내용을 확인할 수 있다.

이때 클래스에서 프로토콜에서 요구하는 생성자를 채택하려면 required 식별자를 써주어야만한다.

 

예외적으로 구조체에서는 생성자 요구사항을 준수할 때에는 required 식별자가 따로 필요하지 않다.

이부분은 class와 struct에 대한 차이로 인하여 알고 있으면 좋을듯 하여 내용을 작성해봤다.

 

< final class에 대한 예제 >

좌측의 이미지는 추가적으로 final class 즉, 상속을 받지도 않고, 해주지도 않을 final class라면 생성자 앞에 required 식별자를 사용하지 않아도 protocol의 요구사항을 지킨 것으로 관주한다.

 

하지만 해당 클래스를 상속해주거나 다른 클래스를 상속받은 경우라면 무조건 required 식별자를 써줘야한다.

그렇지 않으면 우측의 이미지 처럼 에러가 발생하게 된다.

에러 내용을 확인해보면 이니셜라이저 요구사항 init(age : )는 최종 클래스가 아닌 SampleClass의 'required' 이니셜라이저에 의해서만 충족될 수 있다. 

 

즉, required 식별자를 작성하라는 내용이다.

 

이렇게 이번에는 protocol에 대한 요구사항 작성 방법에 대해서 확인을 해보았다.

특별히 별다른 내용은 없고, 해당 규약을 채택하는 경우에 해당 규약을 지키라는 문법의 내용이다.

즉, 정리를 하자면... 로마에 가면 로마의 법을 따르라. 이내용과 동일하다.

반응형

'APPLE > Swift 문법' 카테고리의 다른 글

[ 기초 문법 ] 열거형  (0) 2022.08.22
[ 기초 문법 ] Extension  (0) 2022.08.22
[ 기초 문법 ] guard  (0) 2022.08.19
[ 기초 문법 ] Assert / Preconditions  (0) 2022.08.17
[ 기초 문법 ] 타입 캐스팅  (0) 2022.08.16