Reputation: 63555
I'm trying to define a trait that uses the corresponding companion object, that is, the componion object of the class using the trait.
for example, I have:
:paste
class Parent {
def callMyCompanion = print(Parent.salute)
}
object Parent {
def salute = "Hello from Parent companion object"
}
class Child extends Parent {
}
object Child {
def salute = "Hello from Child companion object"
}
And then I create a parent object:
scala> val p = new Parent()
p: Parent = Parent@1ecf669
scala> p.callMyCompanion
Hello from Parent companion object
But with a child:
scala> val c = new Child()
c: Child = Child@4fd986
scala> c.callMyCompanion
Hello from Parent companion object
I'd like to get: Hello from Child companion object
How can I achieve it???
-- edit to clarify
Thanks for your responses, but in this case callMyCompanion is a dummy method I created just to explain myself, I'm trying to reuse the parent method without having to override it in every class that implements it...
The solution I've found so far was to implement an instance method that uses the companion obejct...
Upvotes: 4
Views: 13101
Reputation: 24403
As I already wrote in the comments, maybe typeclasses can help you here:
trait Greeter[T] {
def salute: Unit
}
object Greeter {
implicit def anyToGreeter[A](x: A) = new {
def salute(implicit greeter: Greeter[A]) = greeter.salute
}
}
class Foo
class Bar extends Foo
implicit object FooGreeter extends Greeter[Foo] {
def salute = println("Hello from FooGreeter.")
}
implicit object BarGreeter extends Greeter[Bar] {
def salute = println("Hello from BarGreeter.")
}
With this I get the following output:
scala> import Greeter._
import Greeter._
scala> new Foo().salute
Hello from FooGreeter.
scala> new Bar().salute
Hello from BarGreeter.
Upvotes: 5
Reputation: 63555
The solution I've found so far was to add a reference to the companion object in the class, so that every instance variable can get to the companion object of it's class
That way, I only have to override the method to get a reference to the companion object...
To do that I had to implement a ParentCompanion trait...
But I don't need to override callMyCompanion, or any other method that needs access to the companion object.
It all would be much simpler if I could get a reference of the companion object via reflection...
the code is something like this
:paste
trait ParentCompanion {
def salute: String
}
class Parent {
def callMyCompanion = print(companion.salute)
def companion: ParentCompanion = Parent
}
object Parent extends ParentCompanion {
def salute = "Hello from Parent companion object"
}
class Child extends Parent {
override def companion = Child
}
object Child extends Companion {
def salute = "Hello from Child companion object"
}
Upvotes: 6
Reputation: 10571
The main problem with actually having access to the companion object without knowing which one it is, is that you basically have a AnyRef
only, which is not very helpful at all.
Another approach would be to use structural typing. I assume that all your different companion objects will have something in common (like the salute
you captured in your ParentCompanion
trait). Then you can do the following:
class Parent {
val companion : {
def salute : String
} = Parent
def foo = println(companion.salute)
}
object Parent {
val salute = "Parent Companion"
}
class Child extends Parent {
override val companion = Child
}
object Child {
val salute = "Child Companion"
}
Given this, every sub-class can override the companion
attribute to point to its corresponding companion object, as long as it satisfies the structural type given in Parent
(i.e. it has to have a salute
in this case).
And you can then call this method on your companion, like this:
scala> (new Parent).foo
Parent Companion
scala> (new Child).foo
Child Companion
Upvotes: 1
Reputation: 5239
This request is tantamount to static overriding. Such a thing does not exist in scala, AFAIK, but you could include an instance method override in Child
that would call its companion object for the message. Something tells me you don't want to do that.
Upvotes: 2