Swift에서 프로토콜은 확장을 통해 새로운 기능을 추가하는 것 뿐만 아니라, 코드의 중복을 줄일 수도 있습니다.
✅ 프로토콜을 확장하지 않고 사용
- 일반적으로 프로토콜을 채택한 커스텀 타입(클래스, 구조체, 열거형)은 프로토콜의 모든 요구사항을 충족하여 사용해야 합니다.
- 같은 프로토콜을 채택하여 사용하는 커스텀 타입이 많을수록 중복되는 필수 기능 코드 또한 많아집니다.
protocol AB{ func a() func b() } class Test1: AB{ func a() { // 중복 코드 print("a") } func b() { // 중복 코드 print("b") } } class Test2: AB{ func a() { // 중복 코드 print("a") } func b() { // 중복 코드 print("b") } } struct Test3: AB{ func a() { // 중복 코드 print("a") } func b() { // 중복 코드 print("b") } }
✅ 프로토콜을 확장하여 사용
- 프로토콜 확장 시 프로토콜의 필수 기능을 미리 작성해 놓으면 채택 후 따로 작성할 필요가 없습니다. (코드 중복 X)
- 즉, 확장을 통해 프로토콜의 필수 기능을 기본으로 구현하여 사용하는 방식입니다.
protocol AB{ func a() func b() } extension AB{ func a(){ //확장을 통해 프로토콜의 필수 기능을 미리 구현 print("a") } func b(){ //확장을 통해 프로토콜의 필수 기능을 미리 구현 print("b") } func newMethod(){ // 확장을 통해 새로 추가한 메서드 print("newMethod") } } class Test1: AB{ } class Test2: AB{ } struct Test3: AB{ } var kim = Test2() kim.a() //a kim.b() //b kim.newMethod() //newMethod
✅ 확장을 통한 프로토콜의 다형성1
확장을 통해 얻은 디폴트(기본) 기능을 재정의하여 사용할 겨우 재정의된 기능을 우선적으로 사용합니다. (인스턴스의 타입과 재정의가 이루어진 클래스(구조체, 열거형)의 타입이 같으면 재정의된 기능을 사용)
protocol AB{ func a() func b() } extension AB{ func a(){ print("a") } func b(){ print("b") } func newMethod(){ // 확장을 통해 새로 추가한 메서드 print("newMethod") } } class Test1: AB{ } class Test2: AB{ func a(){ // 확장을 통해 기본적으로 설정한 기능을 재정의 print("AAA") } func newMethod(){ // 확장을 통해 기본적으로 설정한 기능을 재정의 print("XXXXXX") } } struct Test3: AB{ } var kim = Test2() // kim의 타입은 Test2 kim.a() // AAA //재정의된 메서드를 사용! kim.b() // b kim.newMethod() // XXXXXX //재정의된 메서드를 사용!
✅ 확장을 통한 프로토콜의 다형성2
- 인스턴스의 타입이 프로토콜 타입이라면, 확장을 통해 추가로 얻은 기능을 재정의하여 사용할 수 없습니다.
- 추가로 정의한 기능은 재정의하여 사용할 수 없지만, 필수 기능은 재정의할 수 있습니다.
protocol AB{ func a() // 필수 기능 func b() // 필수 기능 } extension AB{ func a(){ // 필수 기능을 기본으로 구현 print("a") } func b(){ // 필수 기능을 기본으로 구현 print("b") } func newMethod(){ // 확장을 통해 새로 추가한 메서드 print("newMethod") } } class Test1: AB{ } class Test2: AB{ func a(){ // 확장을 통해 기본적으로 구현한 기능을 재정의 print("AAA") } func newMethod(){ // 확장을 통해 기본적으로 구현한 기능을 재정의 print("XXXXXX") } } struct Test3: AB{ } var kim: AB = Test2() // kim의 타입은 AB(프로토콜 타입) kim.a() // AAA //재정의된 메서드를 사용! kim.b() // b //인스턴스의 타입이 프로토콜 타입이기 때문에 재정의된 메서드를 사용할 수 없습니다. kim.newMethod() // newMethod //재정의된 메서드 X, 확장을 통해 새로 추가한 메서드 사용