【问题标题】: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 中的类(即类的每个实例的类型定义)吗?

【问题讨论】:

    标签: scala scope access-modifiers


    【解决方案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 语言时可能会成为“陷阱”。非常简洁的回答;值得我点赞;)。
    猜你喜欢
    • 1970-01-01
    • 2016-04-30
    • 2013-10-10
    • 2014-06-03
    • 2010-10-22
    • 1970-01-01
    • 2023-04-08
    • 2015-05-04
    • 1970-01-01
    相关资源
    最近更新 更多