monnef
monnef

Reputation: 4053

Case class's apply method type

I was trying to use type field, but it seems I did something wrong. It seems to be working with classic classes, but for some reason type of case class's apply doesn't match.

object Common {
    type EntityId = Long
}
import Common._

abstract class IdStore {
  self =>
  type Entity
  type Ref <: IdRef[_]
  type Self <: IdStore {type Entity = self.Entity; type Ref = self.Ref}

  def apply(data: Map[Ref, Entity]): Self

  def data: Map[Ref, Entity]

  def merge(other: Self): Self = apply(data ++ other.data)
}

trait IdRef[T] {
  def id: T
}

trait EntityIdRef extends IdRef[EntityId] {}


class TestStore(val data: Map[IdRef[Int], Object]) extends IdStore {
  override type Entity = Object
  override type Ref = IdRef[Int]
  override type Self = TestStore

  override def apply(data: Map[Ref, Entity]): Self = new TestStore(data)
}

case class TestCaseClassStore(data: Map[IdRef[Int], Object]) extends IdStore {
  override type Entity = Object
  override type Ref = IdRef[Int]
  override type Self = TestCaseClassStore
}

Error

Main.scala:34: error: class TestCaseClassStore needs to be abstract, since method apply in class IdStore of type (data: Map[TestCaseClassStore.this.Ref,TestCaseClassStore.this.Entity])TestCaseClassStore.this.Self is not defined
case class TestCaseClassStore(data: Map[IdRef[Int], Object]) extends IdStore {
           ^
one error found

Code is also available at Ideone.

Upvotes: 1

Views: 283

Answers (3)

Sascha Kolberg
Sascha Kolberg

Reputation: 7162

I suspect you got one detail about case classes wrong:

Case classes do not come with free apply functions!

They come with a companion object that has a factory apply function to create new instances of your case class. That is:

case class Foo(bar: Int)

is similar to

class Foo(val bar: Int)
object Foo {
  def apply(bar: Int): Foo = new Foo(bar)
}

So, in your code

case class TestCaseClassStore(data: Map[IdRef[Int], Object]) extends IdStore {
  override type Entity = Object
  override type Ref = IdRef[Int]
  override type Self = TestCaseClassStore
}

is missing the apply function required in IdStore.

Considering this, are you sure that the apply function defined in IdStore is what you want?

Upvotes: 1

sjrd
sjrd

Reputation: 22095

That's simply because a case class does not have an apply() method. It's companion object gets an apply method, but not the class.

To give you a solution to your problem, though, we would need to know more about what is the expected usage of IdStore and its subclasses. Assuming IdStore is perfect, you probably don't want TestCaseClassStore to be a case class in the first place.

Upvotes: 2

hasumedic
hasumedic

Reputation: 2167

What the error message says and I think it's what's happening, is that you did an override of all types of IdStore, but didn't do so for the "apply" method.

You've got it right for the "TestStore" class, but not in "TestCaseClassStore".

Upvotes: 2

Related Questions