자기 타입에 부합하지 않아 인스턴스화 불가

자기 타입에 부합하지 않아 인스턴스화 불가 (Does Not Conform To Self Type, Cannot Be Instantiated)

자기 타입을 선언한 클래스를, 그 자기 타입을 스스로 만족하지 않는 채로 인스턴스화하려 할 때 나오는 에러예요.

출처: Scala 3 Reference

본문

자기 타입을 갖는 클래스인데 그 자기 타입을 클래스 자신이 만족하지 않는 상태로 인스턴스화하려 하면 이 에러가 발생해요.

클래스가 자기 타입을 선언하면, 모든 인스턴스가 그 타입에 부합하겠다는 약속을 하는 셈이에요. 클래스가 요구되는 타입을 구현하거나 섞어 넣지 않으면 인스턴스를 만들 수 없어요.

예시

trait Database:
  def query(sql: String): String

class Repository:
  self: Database =>
  def findAll(): String = query("SELECT *")

val repo = new Repository

에러 메시지

-- [E059] Type Mismatch Error: example.scala:8:15 ------------------------------
8 |val repo = new Repository
  |               ^^^^^^^^^^
  |Repository does not conform to its self type Database; cannot be instantiated
  |-----------------------------------------------------------------------------
  | Explanation (enabled by `-explain`)
  |- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  | I tried to show that
  |   Repository
  | conforms to
  |   Database
  | but none of the attempts shown below succeeded:
  |
  |   ==> Repository  <:  Database  = false
  |
  | The tests were made under the empty constraint
   -----------------------------------------------------------------------------

해결 방법

// Implement the required self type when instantiating
trait Database:
  def query(sql: String): String

class Repository:
  self: Database =>
  def findAll(): String = query("SELECT *")

val repo = new Repository with Database:
  def query(sql: String): String = s"Executed: $sql"
// Or create a concrete class that mixes in the required trait
trait Database:
  def query(sql: String): String

class Repository:
  self: Database =>
  def findAll(): String = query("SELECT *")

class SqlRepository extends Repository with Database:
  def query(sql: String): String = s"Executed: $sql"

val repo = new SqlRepository

더 알아보기

  • 인스턴스화할 때 요구되는 자기 타입을 함께 구현하거나, 요구 트레이트를 섞어 넣은 구체 클래스를 만들어 쓰면 돼요.