2014-12-05 3 views
5

스위프 일반 타입 제약 조건이 프로토콜 이름 인 경우 해당 프로토콜에 제약이있는 두 가지 유형이 같은 유형이어야합니다. 예를 들면 :How do you say 빠른 일반에

protocol Flier {} 
struct Bird : Flier {} 
struct Insect: Flier {} 
func flockTwoTogether<T:Flier>(f1:T, f2:T) {} 

flockTwoTogether가 아니라 조류와 곤충, 조류와 조류 나 곤충과 곤충 호출 할 수있는 기능. 그것이 내가 원하는 한계 다. 여태까지는 그런대로 잘됐다. 내가 클래스 이름과 같은 일을하려고하면

그러나, 그것은 작동하지 않습니다

class Dog {} 
class NoisyDog : Dog {} 
class WellBehavedDog: Dog {} 
func walkTwoTogether<T:Dog>(d1:T, d2:T) {} 

문제는 내가 WellBehavedDog과 NoisyDog와 walkTwoTogether를 호출 할 수 있다는 것입니다. 이것이 내가 막고 싶은 것입니다.

두 가지 질문이 정말로 여기 있습니다 walkTwoTogether는 WellBehavedDog과 NoisyDog으로 호출 할 수 없습니다 말할 수있는 방법이

  • 있습니까?

  • 이것은 버그입니까? 왜냐하면 일반 함수를 사용할 수 없다면 일반 함수를 사용했을 때와 동일한 결과를 얻을 수 있기 때문에 제네릭 제약이 클래스 이름이되는 것이 왜 유용한 지 알기가 어렵 기 때문입니다.

+0

이것은 나에게 예상되는 것처럼 보입니다. 옵션을 Dog 유형으로 제한했습니다. 두 개의 하위 클래스 모두 해당 유형을 준수하며 선언의 아무 것도 해당 유형을 제한하지 않습니다. 만약 당신이 원하는 것을 할 수있는 방법이 있다면''처럼'where' 절이 필요하다고 기대할 것입니다. 오류. – cmyr

+0

@cmyr 예, 물론 시도해 보았습니다. 그래서 내가하고있는 일이 그것을하는 방법이 아닌지 묻는 이유입니다. 할 수있는 것이지요. :) – matt

+0

'개'가 프로토콜 인 경우 모두 작동합니다.일반 제약 조건은 비 프로토콜 유형에서는 적용될 수 없습니다. * (무언가 타입 삭제) * – mattt

답변

3

하지 대답, 자체, 그러나 아마 좀 더 데이터가 ... 문제는 당신이 호출 할 때입니다 :

walkTwoTogether(NoisyDog(), WellBehavedDog()) 
가 인스턴스를하는 경우로

스위프트는 두 인스턴스를 처리 할 수 Dog (별칭 : upcast) - 우리는 서브 클래스가 A 인 클래스 A에 대한 메소드를 호출 할 수 있어야합니다. (난 당신이 알고 알고 있습니다.)

스위프트 프로토콜 업 캐스팅하지 않기 때문에 그것을 할 수있는 유일한 방법은 슈퍼 클래스가 을 준수하지 않는 서브 클래스에 대한 프로토콜을 지정하는 것입니다 :

protocol Walkable {} 
extension NoisyDog : Walkable {} 
extension WellBehavedDog: Walkable {} 
func walkTwoTogether<T: Dog where T: Walkable>(d1:T, d2:T) { } 

walkTwoTogether(NoisyDog(), WellBehavedDog()) 
// error: type 'Dog' does not conform to protocol 'Walkable' 

오류 메시지가 명시 적으로 무슨 일이 일어나고 있는지 보여줍니다 - walkToTogether 버전을 호출 할 수있는 유일한 방법은 Dog에 서브 클래스의 인스턴스를 업 캐스팅하는 것입니다,하지만 WalkableDog 일치하지 않습니다.

+0

개가 NoisyDog와 구별되는 것은 나 자신에게 원래 제기 한 것처럼 문제를 제시하지 않은 것은 행운입니다! – matt

+0

하위 클래스가 허용되지 않습니다! –

1
나는 그들이해야대로 inout 매개 변수 유형 요구 사항을 변경할 수 있기 때문에이 버그로 간주되어야한다고 말할 것

: 이제

func walkTwoTogether<T:Dog>(inout d1:T, d2:T) { 

그것은 당신이 단지 같은 종류의 두 개의 값을 전달할 수 예상되는 동작이있다 . (Swift 1.2 및 Swift 2 Beta 5에서 테스트되었습니다.)

+0

예 아니요. 이것은 합법적입니다 :'var d : Dog = WellBehavedDog(); 어쨌든, 버그가 있다면, 우리가 말할 수있는 가장 큰 이유는 이것이 모순이라고 생각합니다. 그것은 옳은 것이 분명한 것입니다. – matt

+0

@matt 귀하가 맞을 수도 있습니다. 귀하의 경우에는 두 매개 변수를'inout'으로 표시해야합니다. 흥미롭게도 일반 제약 조건을 사용하지 않으면 거의 동일하게 작동합니다. – Qbyte

+1

나는 그 어느 때보 다 더 당황합니다! 그러나 당신의 자료는 흥미롭지 않습니다. 의심의 여지가 없습니다. – matt

관련 문제