简体   繁体   中英

Are parameters of self reference only available in the specific trait?

I would like to build a case class DataObject .

case class DataObject(parameter: Double)

I want to be able to extend this if necessary with the functionality to call a function. For that I want to be able to extend it with a trait DataObjectFunctionable to make it functionable. This functionality should only be assignable to DataObject because it only makes sense there.

trait DataObjectFunctionable {
  this: DataObject =>
  def unimportantfunction(): Double = parameter + 1
  protected val aFunction: AFunction
}

The exact implementation shall be defined later, thus I keep the Function abstract. Since the extra functionality shall only be a trait for DataObject and a DataObject with the functionality would be DataObjectFunctionable , I give DataObjectFunctionable as input type for the function.

trait AFunction {
    def value(in: DataObjectFunctionable)
}

Now I am going to define my concrete Function.This is all good and well, until I want to excess the inputs parameters.

object MyFunction extends AFunction {
    def value(in: DataObjectFunctionable) = in.parameter + 2
}

Now I am told that in.parameter cannot be resolved. Why is that? this: DataObject => makes sure that DataObject 's members are also available inside DataObjectFunctionable (as seen with unimportantfunction ). Why is it that though this is the case, I don't have parameter at my disposal in MyFunction ? Is it just language design or am I doing something wrong?

What should I do instead? I found that

trait DataObjectFunctionable extends DataObject {
  this: DataObject =>
  def unimportantfunction(): Double = parameter + 1
  protected val aFunction: AFunction
}

solves the issue, but is this really the way to go?

As far as I understand, trait DataObjectFunctionable extends DataObject means "the trait DataObjectFunctionable can only be extended by an DataObject or a subclass of it". However, as far as I understand this: DataObject => means the same... Maybe there is a misunderstanding here that led to my issue.


By the way, this is what I hoped for:

val myObject1 = new DataObject(parameter = 5) extends DataObjectFunctionable {
    override protected val aFunction: AFunction = MyFunction
  }
val myObject2 = new DataObject(parameter = 5)
myObject1.value // returns 5
myObject2.value // that should not be possible, since myObject2 does not get the functionality. I want this to throw a compiler error

Self-reference is akin to "private inheritance". If you don't want the inherited parameters to be "private" to the trait, why don't you make it inherit from DataObject rather than self-reference it?

Alternatively, you can "export" the self-referenced parameter from the trait with something like def param = parameter .

Also, a word of caution: don't extend case classes, not even with traits. It is almost always a bad idea.

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