谜题——用自定义类型暴露私有成员的公共子成员

Posted

技术标签:

【中文标题】谜题——用自定义类型暴露私有成员的公共子成员【英文标题】:Puzzle -- exposing a public sub-member of private member with custom type 【发布时间】:2012-01-31 12:00:13 【问题描述】:

我想做这样的事情(示例被简化,但包含所有关键部分):

class Master

  type DataType = Int
  var counter : DataType = 0


class Slave(private val master : Master)

  val counter = master.counter  // (*)

这里 (*) 我得到错误:

私有值 master 将其定义范围作为类型的一部分进行了转义 从属.this.master.DataType

val counter = master.counter

我理解错误,但我不明白原因 - 类型是类 Master 的一部分,而不是对象 master,所以如果类是私有的,而不是对象,这一点很重要。好吧,至少在理论上是这样。

快速解决方法很容易:

  val counter : Master#DataType = master.counter  

但我相信这是与以前完全相同的代码的显式版本,它“只是”需要更多的输入。那么这是一个功能吗?

问题:

一个类型(这里是 DataType)可以依赖于对象,而不是 Scala 中的类(即类的每个实例的类型定义)吗?

【问题讨论】:

【参考方案1】:

你想错了

这是与之前完全相同的代码的显式版本

Master#DataTypemaster.DataType 是两种不同的类型。

master.DataType 是那些以master 作为外部对象的DataType 实例的类型。换句话说,正是你问的,但显然master 类型的一部分,如果master不是,则类型不能暴露。

Master#DataType 是任何外部对象的任何DataType 实例的类型(相当于Java 中的Master.DataType)。

回复评论:

类型成员可以在子类(包括只包含一个对象的匿名子类)中被覆盖,但只能被兼容类型覆盖。在您的示例中,DataTypeMaster 中已经是具体的,因此唯一与它兼容的类就是它自己。所以像

val a = new Master 
  override type DataType = String

不会进行类型检查,这是有道理的:你会得到var counter: String = 0,这是无稽之谈。但是

val a = new Master 
  override type DataType = Int

会起作用(但不太有用)。

所以只有重写 abstract 类型的成员才有意义。但是它们以与内部类相同的方式进行类型检查,因此a.DataType 通常被认为与b.DataType 不同——即使它们实际上不能不同!

【讨论】:

谢谢,所以如果我理解正确(但是我相信我没有在“Scala 编程”中读到它——或者它可能滑倒了),你可以为类的每个实例定义类型,不仅是每个班级。 感谢您的更新,这非常有价值,不幸的是,我无法为您的帖子投票超过 1 次 :-) 这是 Scala 中有用的东西之一,当来自其他 OOP 语言时可能会成为“陷阱”。非常简洁的回答;值得我点赞;)。

以上是关于谜题——用自定义类型暴露私有成员的公共子成员的主要内容,如果未能解决你的问题,请参考以下文章

第四章:定义封装的类类型

为啥类成员是私有的而属性是公共的? [复制]

将字符串转换为自定义<字符串>

公共类,但私有成员变量? [复制]

子类真的继承私有成员变量吗?

类对象定义 二