简体   繁体   中英

scala: empty constructor for a class with type tag

Consider the following definition for a class.

case class DiscreteProperty[T <: AnyRef](
  name: String,
  sensor: T => String,
  range: Option[List[String]]
)(implicit val tag: ClassTag[T]) extends TypedProperty[T, String] {

  /// some stuff here 
}

I am getting the following error at some point:

Can't instantiate 'edu.illinois.cs.cogcomp.saul.datamodel.property.features.discrete.DiscreteProperty$$anon$2':

I suppose this is because the class doesn't have an empty constructor. How can I define an empty constructor for this class? I tried the following but it is giving me the following error:

  def this() {
    this("funnyName", T => "" ,Option(List()))
  }

And none of these work:

  def this[T]() {
    this("funnyName", T => "" ,Option(List()))
  }

or

  def this[T]() {
    this[T]("funnyName", T => "" ,Option(List()))
  }

Any ideas how to create an empty constructor for this class with type tag?

The issue is that you're not including the implicit parameter in any of your empty constructors. You're treating the primary constructor as having the signature (String, T => String, Option[List[String]]) , but that's not quite right. In fact, it's (String, T => String, Option[List[String]])(ClassTag[T]) (note the ClassTag parameter).

Normally this wouldn't be an issue, since the implicit parameter would be retrieved from the scope of that constructor. However, ClassTag is a bit special - it is filled in at compile time with the ClassTag corresponding to whatever your T is. The problem in each of those auxiliary constructors is that the T is still generic, so the compiler doesn't know which ClassTag to include: there's no implicit parameter available within that scope.

So, how can you fix it? The easiest way is probably to include the implicit parameter in any auxiliary constructors:

def this()(implicit tag: ClassTag[T]) = this("funnyName", T => "", Option(List()))

Note that, you don't need to explicitly proved the ClassTag to the chained constructor; it's now part of the scope and will be used implicitly. Of course, you can decide to do so explicitly like so:

def this()(implicit tag: ClassTag[T]) = this("funnyName", T => "", Option(List()))(tag)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM