简体   繁体   English

scala:定义特征并引用相应的伴随对象

[英]scala: defining a trait and referencing the corresponding companion object

I'm trying to define a trait that uses the corresponding companion object, that is, the componion object of the class using the trait. 我正在尝试定义一个使用相应伴随对象的特征,即使用特征的类的componion对象。

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 我想得到:来自Child伴侣对象的Hello

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... 感谢您的回复,但在这种情况下,callMyCompanion是我创建的一个虚拟方法,只是为了解释自己,我试图重用父方法而不必在每个实现它的类中重写它...

The solution I've found so far was to implement an instance method that uses the companion obejct... 到目前为止我找到的解决方案是实现一个使用伴侣obejct的实例方法......

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... 要做到这一点,我必须实现ParentCompanion特质......

But I don't need to override callMyCompanion, or any other method that needs access to the companion object. 但我不需要覆盖callMyCompanion或任何其他需要访问伴随对象的方法。

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"
}

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.

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. scala,AFAIK中不存在这样的事情,但是你可以在Child中包含一个实例方法覆盖,它会为消息调用它的伴随对象。 Something tells me you don't want to do that. 有事告诉我你不想这样做。

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. 实际上访问伴随对象而不知道它是哪一个的主要问题是,你基本上只有一个AnyRef ,这根本不是很有帮助。

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). 我假设你所有不同的伴侣对象都有一些共同点(比如你在ParentCompanion特征中捕获的salute )。 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 (ie it has to have a salute in this case). 鉴于此,每个子类都可以覆盖companion属性以指向其对应的伴随对象,只要它满足Parent给出的结构类型(即在这种情况下它必须有一个salute )。 And you can then call this method on your companion, like this: 然后你可以在你的同伴上调用这个方法,如下所示:

scala> (new Parent).foo
Parent Companion

scala> (new Child).foo
Child Companion

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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