여기

2017-01-08 7 views
5

과부하의보다 구체적인 방법을 호출하는 방법을 예시 놀이터.여기

test의 모든 버전을 제거하면 제네릭 메서드가 호출됩니다. 클래스 Foo은 프로토콜 P을 준수합니다. Swift는 더 구체적인 이유 때문에 일반 방법을 선택하지 않는 이유는 무엇입니까? 일반적인 것을 호출하는 방법이 있습니까?

+0

가장 간단한 해결책은'test (_ :)'generic (즉, func 테스트 (_ o : T))의'Any' 오버로드를 만드는 것입니다. – Hamish

+0

일반적인 방법은이 경우 더 구체적이지 않습니다. 'test (_ o : Any)'에 대한 인수는'Any'의 _ 유형 중 하나입니다 (유형 자체가 프로토콜 인 경우조차도). 인수로'Foo' 인스턴스를 성공적으로 감쌀 수 있습니다. 구체적인 유형은 일반적인 것보다 구체적이며,'bar.test (...) '를 호출 할 때 과부하 해결에서 우선합니다. 일반적으로 구체적인 타입으로'Any'를 사용하지 않는 것이 좋습니다. 더 나은 접근 방법은 subst입니다. 위의 @Hamish에 의해 설명 된 제약되지 않은 제네릭 (이 경우 제약 된 제네릭은 더 구체적 일 것임)을 사용합니다. – dfri

답변

2

내가 이해 한대로 컴파일러는 항상 오버로드 해결을 수행 할 때 일반 매개 변수보다 명시 적으로 형식화 된 매개 변수를 선호합니다. 따라서 test<T : P>(_ o: T)test(_ o: Any) 사이의 해상도에서는 명시 적 (추상 임에도 불구하고) 매개 변수 유형을 명시하므로 첫 번째 매개 변수는 단순히 자리 표시자인 반면 후자는 선호됩니다. 당신은 일반적인뿐만 아니라 두 번째 오버로드를 만들 경우

따라서, 컴파일러는 지금 모두 명시 적으로 입력 매개 변수를 가지고 있지 않는 한, 최초의 과부하를 선호하지만, 첫 번째 오버로드는보다 긴밀하게 제한된다 :

class Bar { 
    func test<T: P>(_ o: T) { 
     print("Generic", o.getValue()) 
    } 

    func test<T>(_ o: T) { 
     print("Any") 
    } 
} 

let foo = Foo() 
let bar = Bar() 
bar.test(foo) // Generic hello 
당신이 의지에 과부하가 무엇인지에 대한 더 나은 추론 할 수 있습니다로

class Bar { 
    func test<T: P>(_ o: T) { 
     print("Generic", o.getValue()) 
    } 

    func test(_ o: Any) { 
     print("Any") 
    } 
} 

let foo = Foo() 
let bar = Bar() 
(bar.test as (Foo) -> Void)(foo) // Generic hello 

내가 강하게, 첫 번째 방법을 추천 할 것입니다 있지만 :

은 그대로 오버로드를 유지, 유형 캐스팅도 명확하게하기 위해 실행 가능한 해결책이 될 것으로 보인다 선택된다 (일반 가능한 한 프로토콜 형식의 매개 변수보다 일반적으로 선호되어야합니다 (due to the performance benefits of specialisation).

+0

유형으로서의 프로토콜은 일반적으로 추상적으로 언급되지는 않지만 오히려 불명확하다고 생각합니다. 우리가 실제로 이러한 유형의 인스턴스를 가질 수 있기 때문에 전자를 피할 수 있습니다 (일반 유형 홀더로 사용하는 것만은 아님). – dfri

+0

@dfri 어, 나는 항상 추상적 인 (콘크리트의 반의어 인) 것으로 언급했습니다. "이 유형의 인스턴스가있는 것"과 "이 유형의 인스턴스가있는 것"사이에 약간의 차이점을 만들고 싶습니다. 프로토콜 유형의 인스턴스를 가질 수 없으며 프로토콜 유형으로 유형화 된 구체 유형의 인스턴스 만 가질 수 있습니다. 분명히 흥미로운 점이지만, 여기서 "추상적"이라는 단어의 사용에 대한 공동체의 의견에 관심이 있습니다. – Hamish

+0

차별화 된 경우 true. 흥미로운 토론은 추상적 인 타입 홀더 (generic typeholder,'T', above, typealiases)와 프로토콜 ('generic','typealiases/관련 유형). 나는 추상적 인 것에 반응했다. 사용 된 용어 (스위프트, 구체적으로)를 신속한 문서에서 사용하지 않았고, 후자의 경우에는 적어도 "Any"(유형화 된)는 단순히 비표준 유형으로 기술되었다. 언어 안내.하지만 이것은 potatos와 감자입니다. – dfri