2016-07-26 7 views
2

프로토콜 확장에서 인스턴스 메서드를 재정의하려고하는데 몇 가지 문제가 있습니다.Swift에서 프로토콜 확장에서 인스턴스 메소드를 대체하는 방법은 무엇입니까?

맥락에서 나는 다양한 UICollectionViews로 iOS 응용 프로그램을 만들고 있습니다. 이러한 뷰는 다른 데이터베이스의 데이터를 가져오고 (다른 콜백 함수가 필요함) 레이아웃이 매우 다릅니다. (데이터베이스, 레이아웃)의 모든 조합이 가능하기 때문에 방대한 코드 중복없이 멋진 OOP 클래스 계층 구조를 만드는 것은 어렵습니다.

레이아웃 기능 (주로 UICollectionViewDelegateFlowLayout 프로토콜에 정의 된 기능)을 프로토콜 확장에 포함시켜 모든 관련 레이아웃 기능을 구현하도록 확장 된 프로토콜로 주어진 UICollectionView 하위 클래스를 꾸밀 수있는 아이디어가 있었지만 그것의 힘든 시간을 보내고. 문제의 핵심은 아래 코드에 포함되어 있습니다.

class Base { 
    func speak(){ 
     print("Base") 
    } 
} 

class SubA: Base, ProtocolA {} 

class SubB: Base, MyProtocolB {} 

protocol MyProtocolA{ 
    func speak() 
} 

protocol MyProtocolB{ 
    func speak() 
} 

extension MyProtocolA{ 
    func speak(){ 
     print("A")   
    } 
} 

extension MyProtocolA{ 
    func speak(){ 
     print("B")   
    } 
} 

let suba = SubA() 
suba.speak() // prints "Base", I want it to print "A" 

let subb = SubB() 
subb.speak() // prints "Base", I want it to print "B" 

생각들?

+2

"레이아웃 기능 (주로 UICollectionViewDelegateFlowLayout 프로토콜에 정의 된 기능)을 프로토콜 확장에 넣으려는 생각이 들었습니다."그 생각은 잊어 버려. Objective-C는 프로토콜 확장을 지원할 수 없기 때문에 Objective-C는 프로토콜 확장에서 구현을 절대 호출하지 않습니다. 스위프트 전용 기능입니다. – matt

+0

@matt이 질문은 Obj-C에 관한 것이 아닙니다. 그렇습니까? –

+2

@TimVermeulen 네, 맞습니다. 그것은 Swift 프로토콜 확장에서 Objective-C 위임 메소드에 관한 것입니다. – matt

답변

2

프로토콜의 기본 구현은 이러한 프로토콜을 준수하는 클래스가 해당 메서드 자체를 구현하지 않는 경우에만 호출됩니다. 클래스의 메서드는 프로토콜의 기본 구현을 재정의하지만 다른 방법은 사용하지 않습니다.

일반적으로 같은 것을 할 거라고 :

protocol MyProtocolA { 
    func speak() 
} 

protocol MyProtocolB { 
    func speak() 
} 

extension MyProtocolA { 
    func speak() { 
     print("A")   
    } 
} 

extension MyProtocolB { 
    func speak() { 
     print("B")   
    } 
} 

class SubA: MyProtocolA {} 

class SubB: MyProtocolB {} 

let suba = SubA() 
suba.speak() // prints "A" 

let subb = SubB() 
subb.speak() // prints "B" 

을하지만 솔직히

class SubC: MyProtocolA { 
    func speak(){ 
     print("C") 
    } 
} 

let subc = SubC() 
subc.speak() // prints "C" 

을 할 경우이에서 보면, Base의 사용이 예에서는 완전히 중복, 그래서 그것을 제거했습니다. 분명히 다른 이유로 인해 Base에서 서브 클래스해야하는 경우 자유롭게 느껴지십시오. 그러나 요점은 프로토콜의 기본 구현이 클래스의 구현을 오버라이드하지 않고 다른 방향으로 대체한다는 점입니다.

+0

훌륭한 답변, Rob. 추가 정보 : 코드 재사용없이 어떻게 구현 될까요? "this"란, 여기에있는 것처럼 (모든 하위 클래스가 데이터베이스와 레이아웃을 기반으로 기능을 구현해야하는) 2 개 변수의 혼합 및 일치 시나리오를 의미합니다. 이 기능은 계층 구조에 적합하지 않습니다. –

+0

나는 당신을 팔로우하지 않습니다. 무슨 뜻인지 실용적인 예를들 수 있습니까? – Rob

+0

그래서 내 응용 프로그램에는 UICollectionViews가 있습니다. a) 다양한 레이아웃이 있고 b) 다른 데이터베이스의 데이터를 가져옵니다. 좀 더 구체적으로, 나는 "icon"레이아웃과 "detail"레이아웃을 가지고 있는데, 각각은 cellForItemAtIndexPath와 많은 UICollectionViewDelegateFlowLayout 메소드를 오버라이드한다. 그러나 나는 또한 두 개의 데이터베이스를 가지고 있으며 CollectionView가 데이터를 가져 오는 데이터베이스에 따라 다른 코드가 필요하다. 따라서 {Database 1, Database2} x {Icon, Detail}의 모든 조합은 하위 클래스를 필요로합니다. 하지만 코드 복제 없이는 그렇게 할 수 없습니다. –