2011-02-09 3 views
2

어떻게 그 메서드를 정의 할 수 List [+ AnyRef] 반환합니까? 나는 시도했다 :메서드 반환 형식 공분산

def a[T <: AnyRef](): List[T] = List[AnyRef]() 

그러나 그것은 무엇이든지 컴파일하지 않는다.

편집 : 웡에 따라 나는

def a[T <: AnyRef](): List[T] = List[T]() 

를 사용해야하지만, 여기에 예를

def a[T <: AnyRef](): List[T] = if (value) List[T]() else List[Option[String]]() 

옵션에 대한 AnyRef의 하위 유형을 반환 할 수있는 방법은 [문자열이 ]는 Anyref의 자손이지만 컴파일러는 그것을 받아들이지 않는다.

그래서 주된 질문은 내가 metho 문 2 가지 if (value) List[T]() else List[Option[String]]() 수익을 주목

1) : 목록과 같은 공변 리턴 타입과 D [+ AnyRef]

+2

컴파일러가 원하는 것을 알아낼 수없는 경우 추가 설명없이 어떻게 알아 내야합니까? –

+1

인터프리터에 입력하여 알아낼 수 있습니다. –

+0

내 대답 편집을 마쳤습니다. 그것이 너무 많은지 알려주세요 :) –

답변

5

은의가 몇 관찰을하고 반환 형식을 결정하도록 컴파일러시키기의 몇 가지 방법으로 실험 해보자 if 문은 then 및 else 절에서 과 동일한 유형을 반환해야합니다. 따라서이 문이 값을 반환하면 컴파일러는 일반 유형을 추론하여 두 개의 절에 일관된 제약 조건을 적용해야합니다. 당신이 예를 a[scala.io.Source]()를 들어, a()를 호출 할 때

2) T 변수 유형을 알 수는 당신이 통과 정확한 유형에 따라 달라집니다. 메소드 선언에서 T에 상한값 인 T <: AnyRef을주었습니다. 이는 컴파일러가 AnyRef 및 Option [String]의 부속 유형 인 모든 유형의 합집합 인 가장 일반적인 유형을 찾아야 함을 의미합니다.

3) 반환 형식 선언을 제거하여 컴파일러에서 유추되는 반환 형식을 확인하십시오. 즉 def a[T <: AnyRef]() = if (true) List[T]() else List[Option[T]]()입니다. 컴파일러에서 a() 반환 유형 List[AnyRef]을 제공했습니다. 이 유형은 의미가 있습니다. 서브 유형이 AnyRef이고 Option[of that anything T]T 사이의 가장 일반적인 유형에 대한 유일한 가능성 때문입니다.

4) 이제 시도하십시오 def a[T <: AnyRef]() = if (true) List[T]() else List[Option[String]](). 추론 된 반환 유형은 이제 List[java.lang.Object]입니다. 그 이유는 스칼라 2.8의 String 클래스가 실제로 java.lang.String이기 때문에 가장 일반적인 추측에 따르면 가장 일반적인 유형은 scala.* 계층을 벗어나 알려지지 않은 이유로 java.lang.Object으로 끝납니다. AnyRef 이후

5) 정말 java.lang.Object 단지 별칭, 당신은 List[AnyRef]의 반환 유형을 강제로 def a[T <: AnyRef](): List[AnyRef] = if (true) List[T]() else List[Option[String]]() 할 수 있습니다. 기본적으로 슈퍼 클래스를 반환

def a(): List[AnyRef] = ... 

을, 당신은 .asInstanceOf[T]를 사용하여 아래로 돌려 List[AnyRef] 캐스팅해야한다 : 당신은 그냥 AnyRef의 하위 유형을 반환하려면

, 당신은 기본적으로이 작업을 수행 할 수 있습니다.또한 :

def a[T <: AnyRef](): List[T] = List[T]() 

의지는 당신에게 특정 유형 (T)를 제공하지만, 하나 더 구체적이고 다른 수 있습니다 귀하의 예제에서와 같은 if 문에 2 개 개의 다른 형태를 돌려, 항상 그것을 기대할 수 없다 메소드를 호출 할 때 사용자가 제공 한보다 구체적인 유형을 리턴하십시오. 컴파일러는 형식을 보장 할 방법이 없으므로 if 문은 형식 검사만으로 항상 List [T]가됩니다. 나는 그것을 더 명확하게 만들었습니까?

+0

@ 감사하지만 정확히 내가 원했던 것이 아니고 편집을 참조하십시오. – Nutel

3

귀하의 정의 반환 값은 List[T]하지 않은하는 List[AnyRef] 때문에

def a[T <: AnyRef](): List[T] = List[AnyRef]() 

가 컴파일되지 않습니다.

def a[T <: AnyRef](): List[AnyRef] = List[T]() 

을 그대로 질문에 해당하지만, 왕의 대답은 더 유용 할 것입니다 : 다른 방법은 주위 않습니다.

2

메소드를 호출하는 코드에 대해 생각하십시오. 예를 들어,

val x = a() 

x 유형은 무엇입니까? 한 가지는 당신이 수 없습니다 x의 형식이 뭔가에 따라 달라집니다 - 그것은 에만 수 있습니다 위의 라인의 정적 컨텍스트 및 메서드의 서명에 따라 달라집니다. 따라서 T 또는 Option[String]을 반환하는 예제는 메서드 시그니처에서 반환 될 메서드를 알 수 없기 때문에 절대로 작동하지 않습니다.

사용 사례는 무엇입니까? 그런 것을 어떻게 사용하고 싶습니까?