0

I have the following abstract classes:

abstract class Accessor {

  def get(rowkey:String): Option[M2mModel]
  def insertNew(model: M2mModel): Option[M2mModel]


}

abstract class Model(active:Int) {

  @BeanProperty
  var ttl = None

}

My implementation classes are:

object AccountModel {
  val COL_USERNAME = "username"
  val COL_EMAIL = "email"
  val COL_PASSWORD = "password"
  val COL_DOMAIN = "domain"
  val COL_ACTIVE = "active"
  val COL_ROLE = "role"
  val COL_ACLID = "aclid"

  val definedFields = List(COL_USERNAME, COL_EMAIL, COL_PASSWORD, COL_DOMAIN, 
    COL_ACTIVE, COL_ROLE, COL_ACLID)

  def apply(rowkey:String, email:String, password:String) = new AccountModel(rowkey, email, password) 

}


case class AccountModel(rowkey: String, email:String, password: Option[String], 
  username: Option[String], domain: Option[String],
  role: Option[String], active: Int, aclid: Option[String]) extends M2mModel(active) {

  def this(rowkey:String, email:String, password:String) = this(rowkey, email, Some(password),
      None, None, None, 1, None)

}

When I create the Accessor class and implement the insertNew method I get the following error: object creation impossible, since method insertNew in class Accessor of type (model: package.Model)Option[package.Model] is not defined (Note that package.Model does not match package.AccountModel)

Here is my implementing class

object AccountAccess extends Accessor {
 def insertNew(model: AccountModel): Option[AccountModel] = {

    ...do stuff
}

what am i doing wrong?

thanks

chiappone
  • 2,468
  • 2
  • 23
  • 32

2 Answers2

1

The problem here is that the insertNew method requires something of type M2mModel and it can be implemented only by a method that resolves to the same signature.

In Scala, we can solve this in two ways.

Type Parametrization

We can consider the Accessor as a generic class which works with something of type T that extends M2mModel:

abstract class Accessor[T <: M2mModel] {
    def get(rowkey:String): Option[T]
    def insertNew(model: T): Option[T]
}

And extend AccountAccess from this like so:

object AccountAccess extends Accessor[AccountModel] {
    def insertNew(model: AccountModel): Option[AccountModel] = {
        ???
    }

    def get(rowkey: String) = ???
}

Abstract type members

We can consider Accessor to be a class which in its implementation handles objects of some abstract type T that extends M2mModel:

abstract class Accessor {

    type T <: M2mModel

    def get(rowkey:String): Option[T]
    def insertNew(model: T): Option[T]

}

Extending classes, in this case AccountAccess, should specify what this type T is supposed to be:

object AccountAccess extends Accessor {

    type T = AccountModel

    def get(rowkey: String) = ???

    def insertNew(model: AccountModel) = ???
}

Personally, I do belive that the second choice is the better approach.

You can find a very interesting discussion about this here:

Scala: Abstract types vs generics

Do read it since it will help you solve this kind of problems in a very elegant and modular way in the future.

Community
  • 1
  • 1
Marius Danila
  • 10,003
  • 2
  • 31
  • 37
0

I think you're narrowing the scope of insertNew in your object, so it no longer meets it's requirements. Your insertNew method can only take classes greater than M2mModel not lower.

This should work:

 def insertNew(model: M2mModel): Option[M2mModel]

And this:

 def insertNew(model: Any): Option[Any]

Imagine if you passed this object to something that only knew about M2mModel and not AccountModel. The function insertNew only takes AccountModel so another M2mModel wouldn't work.

Noah
  • 13,323
  • 4
  • 33
  • 44