如何从 Scala 中的重写方法返回正确的类型? [英] How to return correct type from an overriden method in Scala?

查看:90
本文介绍了如何从 Scala 中的重写方法返回正确的类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

作为 Scala 的新手,我偶然发现了 SubClassing 和 Overriding 方法这个看似简单的点.

As a newbie in Scala, I have stumbled on this seemingly easy point of SubClassing and Overriding methods.

我有专门的一个集合:

    class SpecializedSet [T](s:Int, b: Boolean) (implicit ordering: Ordering [T]) extends TreeSet [T] { 
      override def + (t: T): SpecializedSet [T] = {

           if (this.isEmpty) {

              s = s + 1

              // I want to add an element to the Set
              super.+ (t) 

           }
           ....
       }

在使用这门课的地方,我这样做:

At the site of using this class, I do:

       class Driver {

         var e = new SpecializedSet [MyEarlierDefinedType](3,false);

         ......

         val elem1 = new MyEarlierDefinedType()

         e = e + eleme1 

         ......
     }

编译器立即抱怨:

类型不匹配;发现:scala.collection.immutable.TreeSet[T] 需要:org.personal.exercises.SpecializedSet[T]

type mismatch; found : scala.collection.immutable.TreeSet[T] required: org.personal.exercises.SpecializedSet[T]

我知道被覆盖的 '+' 方法必须返回一个 'SpecializedSet' 类型 - 一个子类型 - 而仅仅调用 super.+() 并不能实现这一点.

I understand that the overridden '+' method has to return a 'SpecializedSet' type - a Subtype - and a mere call to super.+() doesn't achieve that.

super.+() 返回的不是同一个 TreeSet,它是一个新的 TreeSet 来代替它.我想我现在必须自己创建一个 SpecializedSet() 的新实例,使用这个新的 TreeSet.我被困在这里.我如何创建一个新的 SpecializedSet(),使用 TreeSet 这是它的超类型?在这种情况下,Scala 世界中的习语是什么?在这里使用 asInstanceOf() 是最合适和最简短的答案吗?但是,不是一直不鼓励使用这种方法吗?

It is not the same TreeSet that super.+() returns, it is a new TreeSet created in its place. I am thinking that I have to now create a new instance of SpecializedSet() myself, using this new TreeSet. I am stuck here. How do I create a new SpecializedSet(), using a TreeSet which is its Supertype? What is the idiom in the Scala world to use in such cases? Is use of asInstanceOf() the most appropriate and short answer here? But, isn't use of that method discouraged all along?

我是否必须创建一个 SpecializedSet 的伴随对象,在其中定义一个 apply() 方法?或者,我是否必须更深入地使用 Scala:如何编写返回类型为接收器的实现类型的对象的方法子类和返回类型 以及其他相关链接?或者,按照在 http://www.scala-lang.org/docu/files/collections-api/collections-impl.html?

Do I have to create a companion object of SpecializedSet defining an apply() method therein? Alternatively, do I have to go much deeper and use the concept of Traits described in Scala: how to write method that returns object typed to implementation type of receiver and Subclasses and return types and other related links? Or, follow the more complicated direction of creating Builders like in http://www.scala-lang.org/docu/files/collections-api/collections-impl.html?

我也经历过这个问题(和答案):扩展 Scala 集合 -它们当然很有用 - 但不知何故,我认为它比我理解的要多.例如,该链接中的解决方案之一是在函数签名中明确提及 Baseclass 的类型,因此:

I have gone through this question (and answers) too: Extending a Scala collection - and they are certainly useful - but somehow I think there is more to it than I have understood. For example, one of the solutions in that link is to explicitly mention the type of Baseclass in the function signature, thus:

      override def + (t: T): TreeSet [T] = { // instead of SpecializedSet 
             ......

但是,在某种程度上,这不是违反了方法调用者的期望吗?我很困惑.

But, then isn't it a violation of the expectation of the caller of the method, in a way? I am confused.

解决方案是否必须像这些链接中概述的那样参与?我缺少的明显点是什么?任何指针都会有所帮助.我已经进行了相当多的搜索,但如果我的问题是重复的,请耐心等待并指导我.

Does the solution have to be so involved as outlined in these links? What is the obvious point that I am missing? Any pointer will be helpful. I have searched to quite a good extent but if my question is a duplicate, please bear with me and direct me.

推荐答案

我更愿意扩展相应的 trait 并通过组合而不是直接继承来使用类:

I would prefer to extend the corresponding trait and use the class through composition instead of direct inheritance:

class SpecializedSet[T](s: Int, b: Boolean)(implicit ordering: Ordering[T]) extends SortedSet[T] {
  private var ts = new TreeSet[T]()
  override def +(t: T): SpecializedSet[T] = {
    ts += t
    this
  }
  override def -(t: T): SpecializedSet[T] = {
    ts -= t
    this
  }
  override def contains(t: T): Boolean = ts.contains(t)
  override def iterator(): Iterator[T] = ts.iterator
  override def ordering(): Ordering[T] = ts.ordering
  override def rangeImpl(from: Option[T], until: Option[T]) = ts.rangeImpl(from, until)
}

我认为这种方法对新手更友好,因为它避免了直接的类继承和(直接)调用 super.这个非常简单的解决方案的缺点是我们引入了可变性.这可以通过稍微重新设计构造函数来解决,以便可以使成员成为 val 并真正返回一个新修改的 SpecializedSet 实例而不是 this.

I think this approach is more newbie friendly since it avoids direct class inheritance and (direct) calls to super. The drawback of this very simple solution is that we introduced mutability. This could be solved by redesigning the constructor a bit so that it is possible to make the member a val and really return a new modified SpecializedSet instance instead of this.

这篇关于如何从 Scala 中的重写方法返回正确的类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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