返回介绍

数学基础

统计学习

深度学习

工具

Scala

三、访问级别

发布于 2023-07-17 23:38:23 字数 7212 浏览 0 评论 0 收藏 0

  1. Scala 中,默认的访问级别是 public 。通过private 修饰符可以将字段或者方法变成私有。

    
    
    xxxxxxxxxx
    class C(n:Int,s:String) { private val num:Int = n //私有字段 private val name:String = s }
  2. 包、类和对象的成员可以标上privateprotected 这样的访问修饰符。这些修饰符对成员的访问限定在特定的代码区域。

  3. Scala 对访问修饰符的处理大体上与Java 保持一致,但是也有一些重要区别。

3.1 private

  1. Scala 对私有成员的处理跟Java 类似:标记为private 的成员只有在包含该定义的类或者对象的内部可见。

    
    
    xxxxxxxxxx
    class Outer{ class Inner { private def f() = println("Inner f") class InnerMost { f() // 内部访问:可以调用 } } (new Inner).f() // 外部访问:编译错误,无法访问 f }
    • Scala 中,这个规则同样适用于内部类。Scala 在一致性上做的比Java 更好。

      如上例所示:

      • 第一次调用f 是包含在 Inner 类的内部,因此可以访问。
      • 第二次调用f 时发生在Inner 类的外部,因此无法访问。
    • Java 中,两种访问都可以进行。因为在Java 中,可以从外部类访问其内部类的私有成员。

3.2 protected

  1. Java 相比,Scalaprotected 成员的访问也更加严格。在Scala 中,protected 成员只能从定义该成员的子类、或者该成员本身访问。而在Java 中,允许同一个包内的其它类访问这个类的受保护成员。

    
    
    xxxxxxxxxx
    package p { class Parent { protected def f() = println("Parent f") } class Child extends Parent { f() // 子类可以访问父类的 protected 成员 } class Other { (new Parent).f() // 同一个包内,在 Java 中允许访问; 在 Scala 中无法访问 } }

3.3 public

  1. Scala 并没有专门的修饰符来标记公有成员,任何未被标记为 privateprotected 的成员都是公有的。

    公有成员可以从任何位置访问到。

3.4 保护的范围

  1. 我们可以通过限定词对Scala 中的访问修饰符机制进行增强。形如private[X] 或者 protected[X] 的含义是:对此成员的访问限制”上至“ X 都是私有的或者受保护的。其中 X 表示某个包含该定义的包、类或者单例对象。

  2. 带限定词的访问修饰符允许我们对成员的可见性做非常细粒度的控制,尤其是允许我们表达Java 中访问限制的语义,如:包内私有、包内受保护、到最外层嵌套类范围内私有等。

    通过这种方法,我们还可以表达Java 中无法表示的访问规则。

    这种机制对于横跨多个包的大工程非常有用。可以定义对工程中某些子包可见、但是对外部不可见的实体。这在Java 中是无法做到的,因为Java 中一旦定义越过了包的边界,它就对整个世界可见了。

  3. 示例:

    
    
    xxxxxxxxxx
    package root_p ​ package first_p { private[root_p] class Outer { // Outer 对包 root_p 内所有类和对象可见 protected[first_p] def f1()={} // f1 对包 first_p 内所有类和对象可见 class Inner{ private[Outer] val num1 = 0 // num1 对类 Outer 内所有类和对象可见 private[Inner] val num2 = 0 // num2 对类 Inner 内所有类和对象可见 } private[this] val num3 = 0 // num3 仅在当前对象内访问 } } ​ package second_p { import first_p._ // 导入 first_p 所有成员 object Obj { private[second_p] val value = new Outer } }
    • private 限定词的用法:

      • private[root_p] Outer: 类Outerroot_p 包内的所有类和对象都可见,但是对于root_p 包之外的代码都无法访问 Outer

        其公共访问范围为:root_p 包内访问。

      • private[first_p] def f1()={} :方法 f1first_p 包内的所有类和对象都可见,但是对于 first_p 包之外的代码都无法访问。

        其公共访问范围为:first_p 包内访问。它等价于Javapackage 可见性。

      • private[Outer] val num1:变量num1Outer 类内的所有类和对象都可见,但是对于 Outer 类外的代码都无法访问。

        其公共访问范围为:Outer 类内访问。它等价于Javaprivate

      • private[Inner] val num2:变量num2Inner 类内的所有类和对象都可见,但是对于 Inner 类外的代码都无法访问。

        其公共访问范围为:Inner 类内访问。它等价于Scalaprivate

      • private[this] val num3:变量 num3 仅在包含该定义的同一个对象内访问,这样的定义被称作是对象私有的object-private

        这意味着所有对它的访问不仅必须来自于Outer 类的内部,还必须是来自于Outer 的同一个实例。因此将一个成员标记为private[this] 保证了它不会被同一个类的其它对象看到。

        
        
        xxxxxxxxxx
        class C(n:Int) { private val age:Int = n def is_less(other:C) = this.age <= other.age // other.age 可以访问 } ​ println(new C(10).is_less(new C(20))) // 输出: true ​ class C2(n:Int) { private[this] val age:Int = n def is_less(other:C) = this.age <= other.age // other.age 无法访问 }
    • protected 限定词的用法:所有的限定词都可以应用在protected 上,跟private 上的用法一样。

      即:如果我们在类C 中使用protected[X] 这个修饰符,则C 的所有子类,以及X 表示的包、类或对象中,都能访问这个被标记的定义。

      如:protected[first_p] def f1() :方法f1 对包first_p 内的所有类和对象都可见,也对Outer 任何子类内部的所有类和对象可见。因此其含义就和Javaprotected 完全一样。

  4. Java 中,静态成员和实例成员同属于一个类,因此访问修饰符对它们的应用方式是统一的。

    由于Scala 没有静态成员,而是用伴生对象来承载那些只存在一次的成员。因此Scala 的访问规则在privateprotected 的处理上给伴生对象和类保留了特权。

    一个类会将它的所有访问权限和它的伴生对象共享,反之亦然。即:一个对象可以访问它的伴生类的所有私有成员,一个类也可以访问它的伴生对象的所有私有成员。

  5. ScalaJava 在修饰符的方面的确很相似,但是有一个重要例外:protected static

    • Java 中,类Cprotected static 成员可以被C 的所有子类访问。
    • 对于Scala 的伴生对象而言,protecte 成员没有任何意义,因为单例对象没有子类。

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

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

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文