모호한 참조
모호한 참조 (Ambiguous Reference)
식별자 하나가 둘 이상의 정의를 가리킬 수 있어 컴파일러가 어느 쪽을 쓸지 못 정할 때 나오는 에러예요.
본문
식별자가 둘 이상의 서로 다른 정의를 가리킬 수 있고, 컴파일러가 그중 하나를 결정하지 못할 때 이 에러가 발생해요.
이름 바인딩의 여러 종류에는 우선순위가 있고, 높은 것부터 낮은 것까지 순서는 이래요.
- 포함하는 스코프(enclosing scope) 안의 정의
- 상속된 정의와 패키지의 최상위 정의(top-level definition)
- 특정 이름을 import 하면서 도입된 이름
- 와일드카드(wildcard) import 로 도입된 이름
- 다른 파일에 있는 패키지의 정의
정의는 import 보다 우선한다는 점, 그리고 안쪽 스코프의 바인딩이 바깥쪽 스코프의 더 높은 우선순위 바인딩을 가릴(shadow) 수 없다는 점을 기억해 두세요.
예시
import scala.collection.immutable.Seq
import scala.collection.mutable.Seq
val items = Seq(1, 2, 3)
에러 메시지
-- [E049] Reference Error: example.scala:4:12 ----------------------------------
4 |val items = Seq(1, 2, 3)
| ^^^
| Reference to Seq is ambiguous.
| It is both imported by name by import scala.collection.immutable.Seq
| and imported by name subsequently by import scala.collection.mutable.Seq
|-----------------------------------------------------------------------------
| Explanation (enabled by `-explain`)
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| The identifier Seq is ambiguous because two name bindings of equal precedence
| were introduced in the same scope.
|
| The precedence of the different kinds of name bindings, from highest to lowest, is:
| - Definitions in an enclosing scope
| - Inherited definitions and top-level definitions in packages
| - Names introduced by import of a specific name
| - Names introduced by wildcard import
| - Definitions from packages in other files
| Note:
| - As a rule, definitions take precedence over imports.
| - Definitions in an enclosing scope take precedence over inherited definitions,
| which can result in ambiguities in nested classes.
| - When importing, you can avoid naming conflicts by renaming:
| import scala.{Seq => SeqTick}
-----------------------------------------------------------------------------
해결 방법
// Use a rename to avoid the conflict
import scala.collection.immutable.Seq
import scala.collection.mutable.{Seq as MutableSeq}
val items = Seq(1, 2, 3)
val mutableItems = MutableSeq(1, 2, 3)
import scala.collection.{immutable, mutable}
// Or use qualified names
val items = immutable.Seq(1, 2, 3)
val mutableItems = mutable.Seq(1, 2, 3)
// Or import only what you need
import scala.collection.immutable.Seq
val items = Seq(1, 2, 3)
더 알아보기
- 우선순위가 같은 두 바인딩이 같은 스코프에 함께 들어오면 그 이름은 모호하다고 판단돼요.
- 이름을 바꿔 import 하거나(rename), 패키지 정규화된 이름(qualified name)을 쓰면 충돌을 피할 수 있어요.