斯卡拉 - 确保从超一个字段用于(Scala - Making sure that a field

2019-10-21 11:14发布

在Scala中,字段在主构造函数声明。 而且,如果它恰好具有相同的名称从超类中的字段,它将使用一个传入相反,这正是我想避免的。 看看下面的例子:

class Parent(protected val changedParam: MyClass)

class Child(changedParam: MyClass) extends Parent(doStuff(changedParam)) {
  def foo() = {
    bar(changedParam) // Uses Child.changedParam, not Parent.changedParam, which is what I want
  }
}

我要让changedParam在孩子指changedParam在父,子不。 有没有办法做到这一点?

Answer 1:

一类的参数是在它的身上看到。 该文件将在一个私人VAL如果需要的话,那就是如果它的方法中使用,而不是仅仅在初始化代码(当然,如果它没有直接声明为有不同的可见性,或VAR一VAL)。

所以changedParamChild阴影的一个在Base 。 为了避免明显的方法是简单地调用它的另一个名字:

class Child(anotherName: MyClass) extends Base(doStuff(anotherName)) {...


Answer 2:

这被认为是脆弱和愤怒。

你得到,如果你遮蔽一个变种稍有缓解:

scala> class A { var a = 1 } ; class B(a: Int) extends A { def f = a }
defined class A
defined class B

scala> val b = new B(42) ; b.a = 7 ; b.f
b: B = B@1376c05c
b.a: Int = 7
res0: Int = 42

scala> :replay -Xlint
Replaying: class A { var a = 1 } ; class B(a: Int) extends A { def f = a }
<console>:7: warning: private[this] value a in class B shadows mutable a inherited from class A.  Changes to a will not be visible within class B - you may want to give them distinct names.
       class A { var a = 1 } ; class B(a: Int) extends A { def f = a }
                                                                   ^
defined class A
defined class B

Replaying: val b = new B(42) ; b.a = 7 ; b.f
b: B = B@f2ff811
b.a: Int = 7
res0: Int = 42

通常情况下,一个阴影val为更加良性的,但你的例子警告将是有益的。



Answer 3:

class Parent(protected val changedParam: MyClass)

trait Child extends Parent {
  def foo() = {
    bar(changedParam)
  }
}

object Child {
  def apply(changedParam: MyClass): Child =
    new Parent(doStuff(changedParam)) with Child
}

不多说了......谈到Child进入trait避免了声明,你不希望在初始化后使用新的临时成员。 然后我用了同伴对象申报的构造。 在使用唯一的区别是,你不必在添加new关键字来实例化Child

测试:

scala> :paste
// Entering paste mode (ctrl-D to finish)

class Parent(protected val changedParam: Int)

trait Child extends Parent {
  def foo() = {
    println(changedParam)
  }
}

object Child {
  def apply(changedParam: Int): Child =
    new Parent(1 + changedParam) with Child
}

// Exiting paste mode, now interpreting.

defined class Parent
defined trait Child
defined object Child

scala> Child(42).foo()
43


Answer 4:

1)使用显式调用ParentasInstanceOf

package demo {
  // remove protected or make it protected[demo]
  class Parent(protected[demo] val changedParam: MyClass)

  class Child(changedParam: MyClass)
    extends Parent(doStuff(changedParam)) {
    def foo() = {
      bar(this.asInstanceOf[Parent].changedParam)
    }
  }
}

2)使用早期初始化的语法:

class Parent(protected val changedParam: MyClass)

class Child(changedParam: MyClass) extends {
  val superChangedParam = doStuff(changedParam)
} with Parent(superChangedParam) {
  def foo() = {
    bar(superChangedParam)
  }
}

尽管如此,最好的解决办法就是给不同的名称,以您的PARAM。



文章来源: Scala - Making sure that a field from the superclass is used
标签: scala