jbrown jbrown - 2 months ago 9
Scala Question

How to require the same parameter type between scala traits?

I am working on a web server to process a registration form and save it to a datastore. I want this to be a library and work with different instances of registration forms.

I have the following:

trait RegistrationForm

case class SimpleRegistrationForm(name: String,
email: String,
username: String,
password: String) extends RegistrationForm


I want any subclass of
RegistrationForm
to be acceptable to my server.

I have the following traits:

/**
* Interface for saving to a datastore
*/
trait RegistrationDataStore[T <: RegistrationForm] {
def save(form: T): Either[DataStoreException, String]
}


/**
* Trait to handle the form.
*/
trait RegistrationService[T <: RegistrationForm] {
def handleForm(form: T): Either[AkkaHttpExtensionsException, String]
}


And an implementation:

class RegistrationServiceImpl[T <: RegistrationForm](
registrationDataStore: RegistrationDataStore[T])
extends RegistrationService[T] {

def handleForm(form: T): Either[AkkaHttpExtensionsException, String] = {

registrationDataStore.save(form)
}


My server basically looks like this:

object Server {
...
val registrationService = new RegistrationServiceImpl[SimpleRegistrationForm](
new RegistrationMockDataStore[SimpleRegistrationForm]())
...
}


How can I require that the same form subclass is passed as type parameters to implementations of both
RegistrationService
and
RegistrationDataStore
? At the moment, won't they both accept independent subclasses of
RegistrationForm
(I can't test because this doesn't yet compile)? E.g. will the following be valid, and if so, how can I prevent it?

val registrationService = new RegistrationServiceImpl[SimpleRegistrationForm](
new RegistrationMockDataStore[SomeOtherRegistrationForm]())


How can I force the compiler to make sure they are the same subclass of
RegistrationForm
?

Answer

No, it won't be valid. Your constructor parameter is registrationDataStore: RegistrationDataStore[T], so when you write new RegistrationServiceImpl[SimpleRegistrationForm](something), something must be a RegistrationDataStore[SimpleRegistrationForm].

Comments