Scala:如何在超类中引用扩展类的类型? [英] Scala: how to refer to the type of an extending class in a superclass?

查看:53
本文介绍了Scala:如何在超类中引用扩展类的类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有办法在 Parent 中定义类型 T,这样 T 将始终成为扩展类的实际类型(在这种情况下 Child)?

Is there a way to define a type T in Parent such that T will always become the actual type of the extending class (in this case Child)?

Parent 中,我想强制/声明 T 始终是扩展类型,就好像我会写 type T="type_of_the_extending_class" 在每个实际扩展类中,而无需在 Child1 等中实际写下 type T=Child1 行.

In Parent, I want to enforce/declare T to be always the extending type, as if I would have written type T="type_of_the_extending_class" in each actual extending class without actually writing down the lines type T=Child1 in Child1 etc.

所以 Child1 的方法应该只接受 Child1 对象作为参数,而 Child2 的方法应该只接受 Child2 对象.有没有更简单的方法来强制执行?有没有办法不用在每个 ChildX 类中编写 type T=ChildX ?有没有没有这个样板的方法?

So Child1's method only should accept Child1 objects as parameter and Child2's method should only accept Child2 objects. Is there a simpler way to enforce this? Is there a way without writing type T=ChildX in each ChildX class ? Is there a way without this boilerplate?

我一直在 Scala 书籍中寻找解决方案,但没有找到.

I've been searching for a solution in Scala books but did not find any.

abstract class Parent{
  type T<:Parent
  def method(t:T) 
}

class Child1 extends Parent{
  type T=Child1
  override def method(t:T)=t.child1method
  def child1method=println("child1's method")
}

class Child2 extends Parent{
  type T=Child2
  override def method(t:T)=t.child2method
  def child2method=println("child2's method")
}

推荐答案

这个问题的标准解决方案是F 有界多态性(不是特定于 Scala 的——你会发现它用在 Java 等中):

The standard solution to this problem is F-bounded polymorphism (which isn't Scala-specific—you'll find it used in Java, etc.):

trait Parent[T <: Parent[T]] {
  def method(t: T)
}

class Child1 extends Parent[Child1] {
  def method(t: Child1) = println("child1's method")
}

class Child2 extends Parent[Child2] {
  def method(t: Child2) = println("child1's method")
}

顺便说一句,Scala 社区中有一些关于F 有界多态的抱怨——例如 Kris Nuttycombe 说它是 很难正确并导致代码库中的打字混乱",我个人发现在写了几年 Scala 之后,我越来越少地使用它.然而,当您的程序架构导致您需要这种继承时,它正是适合这项工作的工具.

As a side note, there's been some grumbling about F-bounded polymorphism in the Scala community—Kris Nuttycombe for example says it's "tricky to get right and causes typing clutter in the codebase", and I've personally found that I use it less and less often after several years of writing Scala. When your program architecture leads you to need this kind of inheritance, though, it's exactly the right tool for the job.

this.type(在评论中提到)的问题在于它不允许你做大部分你想做的事情——它太具体了:

The problem with this.type (mentioned in the comments) is that it won't allow you to do most of the things you'd reasonably want to do—it's too specific:

scala> abstract class Parent {
     |   def method(t: this.type)
     | }
defined class Parent


scala> class Child1 extends Parent {
     |   def method(t: this.type) = println("child1's method")
     | }
defined class Child1

scala> val a = new Child1
a: Child1 = Child1@19517e9a

scala> val b = new Child1
b: Child1 = Child1@5737e545

scala> a.method(b)
<console>:12: error: type mismatch;
 found   : b.type (with underlying type Child1)
 required: a.type
              a.method(b)
                       ^

我们可以传递给 a.method 的唯一参数是 a 本身.

The only argument we can pass to a.method is a itself.

这篇关于Scala:如何在超类中引用扩展类的类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆