【问题标题】:Access modifier location explanation in scalascala中的访问修饰符位置解释
【发布时间】:2020-05-12 08:00:50
【问题描述】:

我发现我们可以在类之前和类名之后使用访问修饰符。比如我有2个类如下

package com.company.package.sub_package

protected class Animal1{
  def makeSound(): Unit = println("Bow ow")
}


object Animal1{
  def main(args: Array[String])
  {
    val animal = new Animal2()
    animal.makeSound()
  }
}
package com.company.package.sub_package

class Animal2 protected{
  def makeSound(): Unit = println("Meow")
}


object Animal2{
  def main(args: Array[String])
  {
    val animal = new Animal1()
    animal.makeSound()
  }
}

这里在 Animal1 的主方法中显示了一个错误,说 Animal2 不能在对象 Animal1 中访问。

如果我扩展 Animal2 类,子类可以访问父类。

我的理解是,如果我们在类名之后写protected,它对同一个包中的类不可用,如果我在类之前正确,它对包中的所有类都可用,只对它的子类可用,这是一个正确的假设吗?访问修饰符位置的确切意义是什么?

【问题讨论】:

    标签: scala


    【解决方案1】:

    访问修饰符位置的确切意义是什么?

    访问修饰符总是出现在它所修改的访问对象之前。

    在您的第一个示例中,protected 位于类 Animal1 之前,因此它调节对类的访问。

    在您的第二个示例中,protected 位于主构造函数之前,因此它调节对主构造函数的访问。 (注意:它出现在主构造函数之前并不明显,因为 Animal2 有一个空的主构造函数,但 Scala 语言规范说,如果一个类没有参数列表,则插入一个空的 () 参数列表。 )

    所以,你的Animal2 类实际上等价于

    class Animal2 protected () {
      def makeSound(): Unit = println("Meow")
    }
    

    限制对主构造函数的访问的一个典型原因是通过辅助构造函数或伴随模块中的工厂方法来控制实例创建。

    您可以在 Scala 语言规范的section 5.3 Class Definitions 中找到主构造函数的访问修饰符规范。

    【讨论】:

      【解决方案2】:

      class 之前修改的访问权限类似于类中任何其他值的访问修饰符。它指定了该类在包含类之外和子类中的可见性。

      class 之后的访问修饰符适用于构造函数,并指定构造函数在该类的伴随对象之外的可见性

      通常用于隐藏默认构造函数:

      class Positive private(val i: Int)
      
      object Positive {
        def apply(i: Int): Positive = new Positive(math.abs(i))
      }
      

      您可以访问Positivei 字段,但它永远不能为负数。

      【讨论】:

        猜你喜欢
        • 2014-12-27
        • 2018-02-13
        • 1970-01-01
        • 2017-02-19
        • 2014-11-03
        • 2011-10-09
        • 2021-06-24
        • 2015-04-11
        • 1970-01-01
        相关资源
        最近更新 更多