3

我正在尝试定义一个使用相应伴随对象的特征,即使用该特征的类的组合对象。

例如,我有:

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

然后我创建一个父对象:

scala> val p = new Parent()
p: Parent = Parent@1ecf669

scala> p.callMyCompanion
Hello from Parent companion object

但是带着孩子:

scala> val c = new Child()
c: Child = Child@4fd986

scala> c.callMyCompanion
Hello from Parent companion object

我想得到:来自 Child 伴侣对象的 Hello

我怎样才能实现它???

-- 编辑澄清

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

到目前为止我找到的解决方案是实现一个使用伴随对象的实例方法......

4

4 回答 4

6

到目前为止我找到的解决方案是在类中添加对伴随对象的引用,以便每个实例变量都可以访问其类的伴随对象

这样,我只需要重写该方法即可获取对伴随对象的引用...

为此,我必须实现 ParentCompanion 特征......

但我不需要重写 callMyCompanion 或任何其他需要访问伴随对象的方法。

如果我可以通过反射获得伴随对象的引用,这一切都会简单得多......

代码是这样的

: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"
}
于 2012-06-04T05:41:18.830 回答
6

正如我已经在评论中写的那样,也许类型类可以在这里为您提供帮助:

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

有了这个,我得到以下输出:

scala> import Greeter._
import Greeter._

scala> new Foo().salute
Hello from FooGreeter.

scala> new Bar().salute
Hello from BarGreeter.
于 2012-06-04T12:02:18.503 回答
2

这个请求无异于静态覆盖。这样的事情在scala,AFAIK中不存在,但是您可以在其中包含一个实例方法覆盖,Child该方法将调用其消息的伴随对象。有些东西告诉我你不想那样做。

于 2012-06-04T04:13:14.053 回答
1

实际访问伴随对象而不知道它是哪一个的主要问题是你基本上只有一个AnyRef,这根本不是很有帮助。

另一种方法是使用结构类型。我假设你所有不同的伴侣对象都会有一些共同点(比如salute你在你的ParentCompanion特质中捕获的)。然后您可以执行以下操作:

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

鉴于此,每个子类都可以覆盖该companion属性以指向其对应的伴生对象,只要它满足给出的结构类型Parent(即在这种情况下它必须具有 a salute)。然后你可以在你的同伴上调用这个方法,像这样:

scala> (new Parent).foo
Parent Companion

scala> (new Child).foo
Child Companion
于 2012-06-04T06:59:14.423 回答