E177: Constructor Proxy Shadows — 생성자 프록시가 가림

E177: Constructor Proxy Shadows — 생성자 프록시가 가림

내부 클래스의 생성자 프록시에 대한 참조가 같은 이름을 가진 외부 참조(메서드나 객체 등)를 가릴 때 발생하는 에러예요.

출처: Scala 3 Reference

본문

Scala 3에서는 클래스에 대해 생성자 프록시가 자동 생성되어, new를 쓰지 않고도 인스턴스를 만들 수 있어요. 그런데 내부 클래스가 외부 정의(메서드, 객체, 값)와 이름을 공유하면 컴파일러가 어느 쪽을 의도했는지 판단할 수 없어요.

좀 더 자세한 설명 (Longer explanation)

호출의 의미에 모호함이 있어요:

MyClass(...)

내부 클래스의 인스턴스를 만드는 의미일 수도 있어요:

new MyClass(...)

아니면 같은 이름을 가진 외부 메서드/객체를 호출한다는 의미일 수도 있어요:

MyClass(...)

모호함을 없애려면 전자를 의도한다면 명시적인 new를 쓰고, 후자를 의도한다면 전체 프리픽스를 사용해주세요.

예시 (Example)

object Test:
  def MyClass(s: String): String = s

  class Outer:
    class MyClass(s: String)
    val x = MyClass("hello")  // ambiguous: inner class or outer method?

에러 (Error)

-- [E177] Reference Error: example.scala:6:12 ----------------------------------
6 |    val x = MyClass("hello")  // ambiguous: inner class or outer method?
  |            ^^^^^^^
  |           Reference to constructor proxy for class MyClass in class Outer
  |           shadows outer reference to method MyClass in object Test
  |
  |           The instance needs to be created with an explicit `new`.
  |-----------------------------------------------------------------------------
  | Explanation (enabled by `-explain`)
  |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  | There is an ambiguity in the meaning of the call
  |
  |    MyClass(...)
  |
  | It could mean creating an instance of class MyClass in class Outer with
  |
  |    new MyClass(...)
  |
  | Or it could mean calling method MyClass in object Test as in
  |
  |    MyClass(...)
  |
  | To disambiguate, use an explicit `new` if you mean the former,
  | or use a full prefix for MyClass if you mean the latter.
   -----------------------------------------------------------------------------

해결 방법 (Solution)

내부 클래스의 인스턴스를 만들고 싶다면 명시적으로 new를 쓰세요:

object Test:
  def MyClass(s: String): String = s

  class Outer:
    class MyClass(s: String)
    val x = new MyClass("hello")  // explicitly create inner class instance

아니면 전체 프리픽스를 써서 외부 메서드를 호출하세요:

object Test:
  def MyClass(s: String): String = s

  class Outer:
    class MyClass(s: String)
    val x = Test.MyClass("hello")  // explicitly call outer method

더 알아보기

내부 클래스와 외부 정의가 이름을 공유하면 모호함이 생겨요. 의도에 맞게 new나 전체 프리픽스로 명확히 해주세요.