• scala学习手记10


    scala的访问修饰符有如下几个特性:

    • 如果不指定访问修饰符,scala默认为public;
    • 较之Java,scala对protected的定义更加严格;
    • scala可以对可见性进行细粒度的控制。

    scala的默认访问修饰符

    如果没有修饰符,scala会默认把类、字段、方法的访问修饰符当做public。如果要将之调整为private或protected,只需在前面添加对应的修饰符关键字即可。就如下面的程序:

    class Microwave{
      def start() = println("started")
      def stop() = println("stopped")
      private def turnTable() = println("turning table")
    }
    val microwave = new Microwave
    microwave.start()
    microwave.turnTable()//这里错了

    在上面的代码里start和stop两个方法被定义为public类型,可以通过任意Microwave实例访问;turnTable被显示定义为private,这样就不能在Microwave类外部访问它。执行这段代码,就会如注释处声明的一样,会在该处报错:

    image

    protected修饰符

    在scala里,用protected修饰的成员只对本类和派生类可见,同一个包内的其他的类不可见。而且派生类只可以访问本类实例的protected成员。可以通过一个例子看一下:

    package com.zhyea.scala.autos
    
    /**
      * Created by robin on 2016/6/12.
      */
    class Vehicle {
      protected def checkEngine() = println("checked engine")
    }
    
    
    class Car extends Vehicle {
    
      def start() {checkEngine()}
    
      def tow(car : Car) {
        car.checkEngine()
      }
    
      def tow(vehicle: Vehicle){
        vehicle.checkEngine()//会报错
      }
    }
    
    
    class GasStation{
      def fillGas(vehicle : Vehicle){
        vehicle.checkEngine()//会报错
      }
    
    }

    编译这段代码会报错:

    image

    在这段代码里,Vehicle的checkEngine()方法是protected型的。scala允许我们通过Vehicle的派生类Car的实例方法(start())访问这个方法,也允许我们在Car的实例方法里通过Car的实例来访问这个方法,但是不允许在Car的实例方法里用Vehicle的实例访问checkEngine()方法,同一包内的其他类也不行。(好绕,不过真是保护到了极致:只输出方案不输出资源,狗腿子军师)

    细粒度访问控制

    一方面scala对待protected比Java更加严格,另一方面它提供了更多的灵活性和更细粒度的访问规则。

    private和protected可以指定额外的参数。这样,现在可以使用private[AccessQualifier],AccessQualifier可以是this,也可以是其它的类名或包名。这样就可以这么理解:这个成员对所有类都是private,除了自己和AccessQualifier所表示范围内的类。这个概念也是可以递推的,也就是说,如果AccessQualifier是一个类,那么private成员对于AccessQualifier的AccessQualifier也是可见的。

    看一个细粒度访问控制的例子:

    /**
      * Created by robin on 2016/6/13.
      */
    package society {
    
      package professional {
    
        class Executive {
          private[professional] var workDetails = null
          private[society] var friends = null
          private[this] var secret = null
    
          def help(another: Executive) {
            println(another.workDetails)
            println(this.secret)
            println(another.secret) //会报错
          }
        }
    
      }
    
      package social {
    
        class Acquaintance {
          def socialize(person: professional.Executive) {
            println(person.friends)
            println(person.workDetails) //会报错
          }
        }
    
      }
    }

    这段代码里面有一个嵌套包的使用:可以看到,在society包里又声明了professional和social两个包。而且使用包的方式也和之前不一样,之前使用的是点号分隔,文件头声明的方式。

    在类Executive的定义中,三个私有成员变量有着不同的作用范围。workDetails对包professional内的类可见,friends对society包内的类可见,而secret只对当前实例可见。

    所以编译这段代码,在标记报错的地方会报错:

    image

    secret只对当前实例this可见,对Executive的其他实例不可见。workDetails对包professional内的类可见,对society包内的类不可见。因此会报错。

    ##########

  • 相关阅读:
    线性时间选择
    ios理解 Pro Mutlithreading and Memory Management for iOS and OS X with ARC, Grand Central Dispatch, and Blocks
    ef
    c# 采集 获取网页数据内容 一会超时的问题
    entity4.1
    逐渐约束
    entity4.1
    ObjectContext.Refresh
    使用内存表
    MVCdropdownlist
  • 原文地址:https://www.cnblogs.com/amunote/p/5582303.html
Copyright © 2020-2023  润新知