Reputation: 13088
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
Upvotes: 1
Views: 47
Reputation: 40500
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.
Upvotes: 1