Question

Is it possible to create a structured type ins scala to match a class constructor (as opposed to method/function definitions in a class)

To normally match a method call for a class, you would do something like this

type SomeType : {def someMethod:String}

Which allows you to make some method that goes like this

someMethod(a:SomeType) = {
    println(a.someMethod)
}

What would the equivalent be for something like this

type AnotherType: {.......}

Which would work with something like this

class UserId(val id:Long) extends AnyVal

So you can then do something like this

anotherMethod(a:AnotherType,id:Long):AnotherType = {
    new a(id)
}

anotherMethod(UserId,3) // Will return an instance of UserId(3)

I believe this is possible using manifest using runtimeClass and getConstructors, however I am wondering if this is possible using more cleanly (by using something like structured types)

Was it helpful?

Solution

Instead of reflection or structural types, consider using your types companion object as a function value,

scala> case class UserId(val id: Long) extends AnyVal
defined class UserId

scala> def anotherMethod[T, U](ctor: T => U, t: T) = ctor(t)
anotherMethod: [T, U](ctor: T => U, t: T)U

scala> anotherMethod(UserId, 3L)
res0: UserId = UserId(3)

This works as shown for case classes because the Scala compiler will automatically provide the companion object with an apply method which invokes the classes primary constructor and it will also arrange for the companion to extend the appropriate FunctionN trait.

If, for whatever reason, your type can't be a case class you can provide the apply method yourself,

object UserId extends (Long => UserId) {
  def apply(l: Long) = new UserId(l)
}

or you can use a function literal at call sites instead,

anotherMethod(new UserId(_: Long), 3L)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top