2011-03-09 3 views
5

컴파일러가 둘러싸는 클래스에서 메서드를 찾지 않는 이유는 무엇입니까?

다음 스칼라 예제를 살펴보십시오.

class A { 
    def foo(x: Int): Int = x 

    private class B { 
    def foo(): Int = foo(3) 
    } 
} 

컴파일러에서 다음을 컴파일하려고하면 오류 메시지가 나타납니다.

A.scala:5: error: too many arguments for method foo:()Int 
       def foo(): Int = foo(3) 
            ^

어떤 이유로 컴파일러가 둘러싼 클래스 A을 찾지 않습니다. 전화 할 방법을 찾는 것. 클래스 B 만 살펴보고 foo 메소드를 찾아서 적합하지 않은 매개 변수를 취하지 않고 포기합니다. 메서드의 이름을 변경하면 문제없이 작동합니다.

class A { 
    def bar(x: Int): Int = x 

    private class B { 
    def foo(): Int = bar(3) 
    } 
} 

이 경우 컴파일러는 A 클래스를 살펴보고 bar 메서드를 찾습니다.

첫 번째 예제가 작동하지 않는 이유는 무엇입니까? 스칼라의 스펙에 따른 것인가, 아니면 이것은 컴파일러 버그인가? 이것이 규칙에 따르면, 그러면 왜 규칙이 이와 같은 것입니까?

그런데 문제를 해결할 수있는 또 다른 방법은 자체 형식 주석을 사용하는 것입니다.

class A { 
    self => 

    def foo(x: Int): Int = x 

    private class B { 
    def foo(): Int = self.foo(3) 
    } 
} 
+0

이 기능을 사용할 수 있습니까? 클래스 A { DEF foo를 (X : int 치) : int 치 = X 개인 클래스 B는 확장하는 { @Override DEF foo는() : 지능 = foo는 (3) } } –

+1

@Rustem 감사하지만 규칙이 특정 솔루션보다 이런 식의 이유에 더 관심이 있습니다 (이미 자체 유형 주석을 사용하여 좋은 해결책을 가지고 있습니다). – Jesper

답변

10

기술적 클래스 B는 블록이다. 문제를 다음과 같이 줄일 수 있습니다.

def foo(x: Int): Int = x; 
{  
    def foo(): Int = foo(3) 
} 

이렇게하면 똑같은 문제가 발생할 수 있습니다. 블록에 도입 된 모든 이름은 동일한 이름을 가진 모든 것을 쉐도우하므로 (시그니처는 무시합니다 (spec의 2 장 참조) 스펙을 준수합니다. 오버로딩은 클래스 수준에서만 가능합니다. (spec의 6.26.3 장)

관련 문제