我做错了什么? (使用Scala的超类参数)
我有一个家长班和几个孩子班。我想要的是,当在子类的实例上调用特定的 setter 方法时,父类中“同步”的布尔值将设置为 false。应该可以在同步或非同步状态下创建子类。
这就是我的想法:
class A(protected var isSync: Boolean) {
}
class B(var value:String, isSync: Boolean) extends A(isSync) {
override def value_=(value:String): Unit = {
this.isSync = false
this.value = value
}
}
现在,由于多种原因,它无法编译:将 value
分配给 this.value
不明确; var
注释已经定义了 value_=
; this.isSync
引用本地构造函数字段 isSync
,而不是(可写)父字段。
Stack Overflow 上的 这个问题指出我应该使用 __value
(或任何不是 value
的名称)作为构造函数中的 private var
,并自己定义 setter。经过一番修改后,我想出了以下可以编译并运行的代码:
class A(protected var isSync: Boolean) {
}
class B(private var __value: String, private val __isSync: Boolean)
extends A(__isSync) {
def value = __value
def value_=(value: String) = {
this.isSync = false
this.__value = value
}
}
然而,这段代码感觉太腐烂了,以至于现在我怀疑我犯了一个(如果不是更多的话)根本性错误。有人可以纠正我吗?
因此,具体问题是:
- 我正在尝试实现的内容是否存在(以及是否存在)根本缺陷?对于某些上下文:对象在更改时可以(并且可能必须)与服务器同步。
- 将参数传递给您扩展的类的正确/最佳方法是什么?
- 覆盖 var 生成的 setter 的正确/最佳方法是什么(或者通常提供您自己的 setter 实现)?
I have an parent class, and several child classes. What I want is when specific setter methods are called on instances of the child classes, a boolean value for "is synchronized" in the parent class is set to false
. It should be possible to create child classes in either a synchronized or an unsynchronized state.
This is what I came up with:
class A(protected var isSync: Boolean) {
}
class B(var value:String, isSync: Boolean) extends A(isSync) {
override def value_=(value:String): Unit = {
this.isSync = false
this.value = value
}
}
Now, this doesn't compile for a number of reasons: the assignment of value
to this.value
is ambiguous; the var
annotation already defines value_=
; and this.isSync
references the local constructor field isSync
, instead of the (writable) parent field.
This question on Stack Overflow pointed out that I should use __value
(or any name that isn't value
) as a private var
in the constructor, and define the setter myself. After some more tinkering, I came up with the following code that compiles and works:
class A(protected var isSync: Boolean) {
}
class B(private var __value: String, private val __isSync: Boolean)
extends A(__isSync) {
def value = __value
def value_=(value: String) = {
this.isSync = false
this.__value = value
}
}
However, this code feels so rancid that by now I suspect I'm making a (if not more) fundamental mistake. Could anyone please correct me?
Thus the concrete questions are:
- Are there (and if, which) fundamental flaws in what I'm trying to implement? For some context: the objects, when changed, can (and probably have to) be synchronized with a server.
- What is the right/best way to pass parameters to a class you extend?
- What is the right/best way to override the setter generated by
var
(or generally provide your own setter implementation)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
关于问题1:我猜您想跟踪对象自上次复制到服务器以来是否已更改,不是吗?这是明智的,只要服务器上的副本不能被修改:否则确保副本的一致性会更加复杂(副本一致性是谷歌搜索的关键字,但我不推荐它)。
为了清楚起见,我会谈论干净或肮脏 - synchronized 让我想起了
synchronized
Java 语句。关于问题2,您不需要将
__isSync
设为private val
(它将存储在类中),您可以将其保留为构造函数参数。只要不使用它(除了在 A 的构造函数的调用中),__isSync
就不应该在 B 的实例中占用额外的空间。我在那里删除了private val
注释,获得按预期正确编译的代码。关于美观和问题 3:我会简单地避免使用双下划线。 《Scala 编程》(第 18.2 节)中的类似示例只是使用较短的名称。他们还使用
private[this]
来防止同一类的其他实例访问该成员。最后,您可以在类 decl 后删除{}
。在此示例中(即使可能不在您的代码中)。因此我们会得到这样的代码,它与我已经提到的示例很接近:
About question 1: I guess that you want to track whether the object has been changed since last time it was copied to the server, don't you? That's sensible, as long as the copy on the server cannot be modified: otherwise ensuring consistency of the replica is more complex (replica consistency is the keyword for googling, but I wouldn't recommend it).
For clarity, I would talking about being clean or dirty - synchronized reminds me too closely of the
synchronized
Java statement.About question 2, you don't need to make
__isSync
aprivate val
(which will be stored in the class), you can leave it as a constructor parameter. As long as it is not used (other than in the invocation of A's constructor)__isSync
should not take additional space in instances of B. I removed theprivate val
annotation there, obtaining this code which compiles correctly as expected.About aesthetics and question 3: I would simply avoid the double underscore. Similar examples from Programming in Scala (Sec 18.2) simply use shorter names. They also use
private[this]
to prevent access to the member from other instances of the same class. Finally, you can remove{}
after the class decl. in this example (even if maybe not in your code).Thus we'd get code like this, which is close to the examples I already mentioned: