E169: TargetName On Top-Level Class — 최상위 클래스에 붙은 @targetName

E169: TargetName On Top-Level Class — 최상위 클래스에 붙은 @targetName

@targetName 애노테이션을 최상위 클래스·트레이트·객체에 적용할 때 발생하는 에러예요.

출처: Scala 3 Reference

본문

@targetName 애노테이션은 주로 상호운용성(interoperability)을 위해 생성된 바이트코드에서 정의에 대체 이름을 붙여주는 데 쓰여요. 그런데 최상위 타입 정의에는 적용할 수 없어요. 왜냐하면 바이트코드의 클래스 이름이 파일명과 패키지 구조와 일치해야 하기 때문이죠.

예시 (Example)

import scala.annotation.targetName

@targetName("Foo") class MyClass

에러 (Error)

-- [E169] Syntax Error: example.scala:3:25 -------------------------------------
3 |@targetName("Foo") class MyClass
  |                         ^
  |             @targetName annotation not allowed on top-level class MyClass
  |-----------------------------------------------------------------------------
  | Explanation (enabled by `-explain`)
  |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  | The @targetName annotation may be applied to a top-level val or def, but not
  | a top-level class, trait, or object.
  |
  | This restriction is due to the naming convention of Java classfiles, whose filenames
  | are based on the name of the class defined within. If @targetName were permitted
  | here, the name of the classfile would be based on the target name, and the compiler
  | could not associate that classfile with the Scala-visible defined name of the class.
  |
  | If your use case requires @targetName, consider wrapping class MyClass in an object
  | (and possibly exporting it), as in the following example:
  |
  | object Wrapper:
  |   @targetName("Foo") class MyClass { ... }
  |
  | export Wrapper.MyClass  // optional
   -----------------------------------------------------------------------------

해결 방법 (Solution)

import scala.annotation.targetName

// @targetName can be used on methods and vals
class MyClass {
  @targetName("addOne") def ++(x: Int): Int = x + 1
}
import scala.annotation.targetName

// Wrap in an object if you need targetName on a class
object Wrapper {
  @targetName("FooClass") class MyClass
}

더 알아보기

@targetName은 메서드나 val에는 언제든 붙일 수 있어요. 클래스에 꼭 필요하다면 객체 안에 감싸고 export로 꺼내 쓰는 방법을 권장해요.