Udemy iOS by Angela Yu / Section 13 / Protocols

Garam·2023년 7월 4일
0

Udemy iOS by Angela Yu

목록 보기
8/9
post-thumbnail

Protocols

사전적 의미: 규약, 협약.



protocol MyProtocol {
	//Define requirements
}

struct Mystruct: MyProtocol {}
class MyClass: MyProtocol {}

스위프트에서 프로토콜은 '자격증'과 비슷하다.

만약 내가 구조대원 자격증을 따고 싶다면
수영, 인명구조, 심폐소생술 등을 할수 있어야 할것이다.
이러한 기술들을 보유하지 못하다면 자격증을 딸 수 없다.

프로토콜도 마찬가지이다.
특정 메소드를 의무적으로 포함하지 않으면
프로토콜을 적용했다고 볼 수 없는 것이다.




이제 Protocol을 직접 정의해보자.
우리는 비행 능력을 갖춘 자격증을 만들고싶다.

protocol CanFly {
    func fly()
}

참고로 Protocol의 메소드에는 내용이 없어야 한다.
만약 {}를 삽입하면 다음과 같은 에러가 발생할 것이다.




우리에게 Bird라는 Class, Airplane이라는 Structure가 있다고 가정해보자.
그리고 우리는 이들에게 비행이라는 속성을 공통적으로 부여할 것이다.


class Bird {
    
    var isFemale = true
    
    func layEgg() {
        if isFemale {
            print("The bird makes a new bird in a shell.")
        }
    }
    
}


struct Airplane {

}

만약 프로토콜 없이 우리가 원하는 작업을 수행한다면
어떤 문제점이 발생할까?




상위 클래스와 하위 클래스의 Inheritance로 인한 일괄적 속성 부여 문제


만약 프로토콜없이 Bird 클래스내에 fly()를 선언했다고 가정해보자. 그렇다면 Bird의 하위 클래스인 Eagle, Penguin에게도 똑같이 fly()가 유전된다.
class Bird {
    
    var isFemale = true
    
    func fly() {
    	print("The bird flaps its wings and lifts off into the sky.")
    }
    
    func layEgg() {
        if isFemale {
            print("The bird makes a new bird in a shell.")
        }
    }
    
}
class Eagle: Bird {
    
    func soar() {
        print("The eagle glides in the air using air currents.")
    }
 
}

class Penguin: Bird {
    
    func swim() {
        print("The penguin paddles through the water.")
    }
    
}





그런데 우리 모두 알다시피 펭귄은 날 수가 없다.
그럼에도 불구하고 다음과 같은 상황이 벌어질 것이다.

let myPenguin = Penguin()
myPenguin.fly()

>>> 실행결과
"The bird flaps its wings and lifts off into the sky."





Structure와의 호환성 문제


Structure에는 Class의 속성을 전달할 수 없다.
그래서 프로토콜없이 Airplane에 Bird의 비행 능력을 전달하려면
Airplane을 Class로 변경하여 Bird의 하위 클래스로 만드는 방법 뿐이다.
그러나 이 방법도 문제점이 많다.

class Airplane: Bird {

	override func fly() {
    	print("The airplane uses its engine to lift off into the air.")
    }
    
}

let airplane = Airplane()
airplane.layEgg

>>> 실행결과
"The bird makes a new bird in a shell."

일단 Airplane은 Bird도 아닌데
Bird의 하위 클래스가 된다는 것이 어불성설일뿐더러
override func를 이용해 fly()의 출력문구를
비행기의 실정에 맞게 수정한다해도
Bird의 속성인 layEgg()를 그대로 유전받아
알을 낳는 비행기가 탄생해버리는 것이다.




이러한 상황에서 프로토콜을 도입하면 모든 문제가 해결된다.
다음은 CanFly 프로토콜을 사용한 코드의 전문이다.


protocol CanFly {
    func fly()
}



class Bird {
    
    var isFemale = true
    
    func layEgg() {
        if isFemale {
            print("The bird makes a new bird in a shell.")
        }
    }
    
}

//subclass of Bird
class Eagle: Bird, CanFly {
    
    func soar() {
        print("The eagle glides in the air using air currents.")
    }
    
    func fly() {
        print("The eagle flaps its wings and lifts off into the sky.")
    }
    
}

//subclass of Bird
class Penguin: Bird {
    
    func swim() {
        print("The penguin paddles through the water.")
    }
    
}

struct Airplane: CanFly {
    func fly() {
        print("The airplane uses its engine to lift off into the air.")
    }
}





이를 도식화하면 다음과 같다.





만약 내가 수영능력을 보유하지 않고 있다면
구조대원 자격증을 딸 수 없겠지?
프로토콜도 같은 원리다.

Eagle에 fly()라는 메소드가 없다면
CanFly 프로토콜을 부여해줄 수 없게된다.





참고로 다음과 같이 여러개의 프로토콜을 함께 선언하는 것도 가능하다.

struct MyStructure: FirstProtocol, AnotherProtocol {
	// structure definition
}

class MyClass: SuperClass, FirstProtocol, AnotherProtocol {
	// class definition
}




0개의 댓글