【问题标题】:Scala var best practice - EncapsulationScala var 最佳实践 - 封装
【发布时间】:2020-04-04 04:29:08
【问题描述】:

例如,我试图了解在 scala 中使用 vars 的最佳做法是什么

class Rectangle() {
 var x:Int = 0
}

或者类似的东西:

class Rectangle() {
 private var _x:Int = 0
 def x:Int = _x
 def x_(newX:Int):Unit = _x=newX
}

哪一个可以被认为是更好的?为什么? 谢谢!

【问题讨论】:

  • 第二个相当于第一个。在您可能希望对 read 提供比写入更广泛的可见性的情况下,第二个可能会更好。但是,最佳实践始终是根本不使用一个,但如果需要,保持范围尽可能小,所以恕我直言,我会选择第二个并改用 private[this]
  • 没有实际用例很难说,因为你应该使用 case class 或 vals 或 vars 所以它真的取决于用例。根据您的问题,我将使用案例类 Rectangle(x:Int)

标签: scala class private encapsulation


【解决方案1】:

正如 Luis 在评论中已经解释的那样,只要您能够避免,就应该避免使用 vars,而像您给出的这样一个简单的案例是可以使用以下方式更好地设计的案例之一:

// Companion object is not necessary in your case
object Rectangle {
   def fromInt(x: Int): Option[Rectangle] = {
     if(x > 0) {
       Some(Rectangle(x))
     } else None
}
final case class Rectangle(x: Int)

当您无法避免在 scala 中使用 var 时,这种情况非常罕见。 Scala 的通用习语是:“让你的变量不可变,除非有充分的理由不这样做”

【讨论】:

  • 是的。你说得对。添加了决赛。对于伴生对象,它更适合用于更复杂的计算,而不是这个简单的示例。在这样的基本示例中,仅使用案例类就足够了。
【解决方案2】:

我试图了解在 scala 中使用 vars 的最佳实践是什么,[...]

最佳做法是根本不使用vars。

哪一个可以被认为是更好的?为什么?

无论如何,第二个基本上等同于编译器为第一个生成的内容,因此使用第二个实际上没有意义。

如果您想为 setter 和 getter 提供不同的可访问性,这有意义,如下所示:

class Rectangle {
 private[this] var _x = 0
 def x = _x
 private def x_=(x: Int) = _x = x
}

如您所见,我为 setter 和 getter 使用了不同的可访问性,因此明确地写出它们是有意义的。否则,就让编译器生成它们。

注意:我对代码做了一些其他更改:

  • 我将 _x 支持字段的可见性更改为 private[this]
  • 我将设置器的名称更改为x_=。这是 setter 的标准命名,它还有一个额外的优势,即它允许您使用 someRectangle.x = 42 语法糖来调用它,使其与字段无法区分。
  • 我添加了一些空格,让代码有呼吸的空间。
  • 我删除了一些返回类型注释。 (这是有争议的。)社区标准是始终在公共接口中注释您的返回类型,但在我看来,如果它们是微不足道的,您可以将它们排除在外。找出0 的类型为Int 并不需要太多脑力。

请注意,您的第一个版本也可以简化:

class Rectangle(var x: Int = 0)

但是,正如其他答案中所述,您确实应该使您的对象不可变。使用案例类很容易创建一个简单的不可变数据对象,其中包含自动为您生成的所有便利功能:

final case class Rectangle(x: Int = 0)

如果您现在想“更改”您的矩形,您可以创建一个新的矩形,它除了x 之外的所有属性都相同(在这种情况下,x 是唯一的属性,但可能还有更多) .为此,Scala 为您生成了一个漂亮的 copy 方法:

val smallRectangle = Rectangle(3)
val enlargedRectangle = smallRectangle.copy(x = 10)

【讨论】:

  • 使用显式返回类型的想法更多是为了传达意图并确保编译器保证正确性,而不是消除程序员的认知负担。是的,对你来说,作者显然比x 是一个Int,但它可能不适合读者,也不适合用户,甚至更不适合下一个作者。通过错误地将0 更改为0.0,在没有人注意到的情况下破坏二进制兼容性并不难。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-11-18
  • 2023-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-24
相关资源
最近更新 更多