scala 中的私有字段设置器

发布于 2024-11-06 08:11:50 字数 237 浏览 1 评论 0原文

让 scala 中的类字段在类之外只读的最佳方法是什么?我意识到我可以做这样的事情:

private var myvalX = 0 // default val
def myval = myvalX
def myval_=(x: Int) { myvalX = x }

但我发现它非常丑陋,因为 _= 运算符以及您需要定义一个单独的 var ,其名称与方法不同。替代方案将非常受欢迎。谢谢你!

what is the best way to have a class field in scala be read-only outside of the class? i realize i can do something like this:

private var myvalX = 0 // default val
def myval = myvalX
def myval_=(x: Int) { myvalX = x }

but i find it extremely ugly due to the _= operator and the fact that you need to define a separate var whose name is different than the methods. alternatives would be very welcome. thank you!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

离笑几人歌 2024-11-13 08:11:50

我认为私有字段和公共字段同名并不是一个好的做法。例如,您编写的

private var myvalX = 0 // default val
def myval = myvalX
def myval_=(x: Int) { myvalX = x }

内容根本不会使 myval 成为只读!您的意思可能

private def myval_=(x: Int) { myvalX = x }

是只读的。但这是一个完美的例子,说明了为什么这是一个坏主意——您要求混淆公共接口和私有实现细节。可能出现的其他问题是用户没有意识到值可能会从他们的下面改变,子类重新定义公共 getter 而没有意识到私有 setter 不可用,等等。

如果您不尝试共享名称,那么很明显需要考虑两件事:您的基础数据以及依赖于该数据的公共接口。

private var myData = 0
def data = myData

那还不错,不是吗?

或者,如果您确实坚持使用这种模式,则可以使用各种技巧让事情看起来更好一些。例如,如果您有一堆字段,您可以

class C {
  abstract class ReadOnly[A] { def value: A }
  private class ReadWrite[A](var value: A) extends ReadOnly[A]

  private implicit def access[A](ro: ReadOnly[A]) = ro.asInstanceOf[ReadWrite[A]]
  def rw[A](a: A): ReadOnly[A] = new ReadWrite(a)

  val data = rw(0)
  val comment = rw("Ho-hum")
}

让 C 类中的任何内容设置 data.valuecomment.value,并且只让其他人读取它们。 (编辑:修改为包含原始示例中的所有好东西,因为如果省略它们,您可能会出错。)

I don't think it's good practice to have private fields and public ones share the same name. For example, you wrote

private var myvalX = 0 // default val
def myval = myvalX
def myval_=(x: Int) { myvalX = x }

which doesn't make myval read-only at all! You probably meant something like

private def myval_=(x: Int) { myvalX = x }

which would be read-only. But this is a perfect example of why it's a bad idea--you are asking for confusion between a public interface and your private implementation details. Other problems that can arise are users not realizing that the value might change out from under them, subclasses redefining the public getter without realizing that the private setter is not available, and so on.

If you don't try to share the name, then it's clearer that there are two things to think about: your underlying data, and the public interface that relies upon that data.

private var myData = 0
def data = myData

That's not so bad, is it?

Alternatively, you can use various tricks to make things look somewhat nicer if you really insist on using this pattern. For example, if you have a bunch of fields you could

class C {
  abstract class ReadOnly[A] { def value: A }
  private class ReadWrite[A](var value: A) extends ReadOnly[A]

  private implicit def access[A](ro: ReadOnly[A]) = ro.asInstanceOf[ReadWrite[A]]
  def rw[A](a: A): ReadOnly[A] = new ReadWrite(a)

  val data = rw(0)
  val comment = rw("Ho-hum")
}

which will let anything in class C set data.value and comment.value, and only let everyone else read them. (Edit: modified to include all the goodies in the original example, since if you omit them you might make errors.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文