scala雾中风景(28): private?public?

栏目: Scala · 发布时间: 6年前

内容简介:scala雾中风景(28): private?public?

记录前些天遇到的一个问题,scala里 protectedprivate 修饰的方法可能在编译为class时变成了 public ,这已经不是第一次遇到,最早遇到是在写一个 java 子类时要覆盖一些父类方法,父类是scala写的一个trait,里面的方法修饰为 protected ,当时IDE提示我override的方法必须声明为 public 感到奇怪反编译了一下父trait果然被声明为了 public

而这次遇到的稍有不同,跟继承没有关系,用下面的demo举例:

➜  cat A.scala
class A {
  private[this] def foo() = {
    List(1,2,3).map(i => bar(i))
  }

  private[this] def bar(i:Int):String = {
    "str:" + i
  }
}

当我们编译上面类之后,里面的 foobar 方法的修饰符最终在class里会有所不同,反编译后可看到 bar 修饰符变成了 public :

➜  cfr-decompiler A
 ...
 public class A {
    private List<String> foo() {
        return (List)List..MODULE$.apply((Seq)Predef..MODULE$.wrapIntArray(new int[]{1, 2, 3})).map((Function1)new scala.Serializable(this){
            public static final long serialVersionUID = 0;
            private final /* synthetic */ A $outer;

            public final String apply(int i) {
                return this.$outer.A$$bar(i);
            }
        }, List..MODULE$.canBuildFrom());
    }

    public String A$$bar(int i) {
        return new StringBuilder().append((Object)"str:").append((Object)BoxesRunTime.boxToInteger((int)i)).toString();
    }
}

终归scala在jvm上要做一些妥协,按上面的实现, foo 里面以闭包的方式使用 bar 的时候,如果保持scala private[this] 的控制粒度,底层的匿名类其实已经无法访问 bar 了。所以scala在编译器的explicitouter环节做了一些向现实妥协的事情

➜  scalac -Xshow-phases
    phase name  id  description
    ----------  --  -----------
        parser   1  parse source into ASTs, perform simple desugaring
         namer   2  resolve names, attach symbols to named trees
packageobjects   3  load package objects
         typer   4  the meat and potatoes: type the trees
        patmat   5  translate match expressions
superaccessors   6  add super accessors in traits and nested classes
    extmethods   7  add extension methods for inline classes
       pickler   8  serialize symbol tables
     refchecks   9  reference/override checking, translate nested objects
       uncurry  10  uncurry, translate function values to anonymous classes
     tailcalls  11  replace tail calls by jumps
    specialize  12  @specialized-driven class and method specialization
 explicitouter  13  this refs to outer pointers
       erasure  14  erase types, add interfaces for traits
   posterasure  15  clean up erased inline classes
      lazyvals  16  allocate bitmaps, translate lazy vals into lazified defs
    lambdalift  17  move nested functions to top level
  constructors  18  move field definitions into constructors
       flatten  19  eliminate inner classes
         mixin  20  mixin composition
       cleanup  21  platform-specific cleanups, generate reflective calls
    delambdafy  22  remove lambdas
         icode  23  generate portable intermediate code
           jvm  24  generate JVM bytecode
      terminal  25  the last phase during a compilation run

在这个阶段,当编译器发现一些 private 的方法会被内部类访问的话,就删除这些 private 修饰符:

➜  scalac -Xprint:explicitouter A.scala
[[syntax trees at end of             explicitouter]] // A.scala
package <empty> {
  class A extends Object {
    def <init>(): A = {
      A.super.<init>();
      ()
    };
    private[this] def foo(): List[String] = immutable.this.List.apply[Int](scala.this.Predef.wrapIntArray(Array[Int]{1, 2, 3})).map[String, List[String]]({
      @SerialVersionUID(value = 0) final <synthetic> class $anonfun extends scala.runtime.AbstractFunction1[Int,String] with Serializable {
        def <init>($outer: A.this.type): <$anon: Int => String> = {
          $anonfun.super.<init>();
          ()
        };
        final def apply(i: Int): String = $anonfun.this.$outer.bar(i);
        <synthetic> <paramaccessor> <artifact> private[this] val $outer: A.this.type = _;
        <synthetic> <stable> <artifact> def $outer(): A.this.type = $anonfun.this.$outer
      };
      (new <$anon: Int => String>(A.this): Int => String)
    }, immutable.this.List.canBuildFrom[String]());
    
    final def bar(i: Int): String = "str:".+(i)
  }
}

上面 barprivate[this] 在这个阶段被删除,而scala不同于java,缺省就是 public ,最终在class里变成了 public


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

冷启动

冷启动

高臻臻 / 人民邮电出版社 / 2018-5 / 59.80元

本书针对中小企业做营销没预算、没用户的痛点,系统梳理冷启动项目的思维和策略,帮助营销和运营人员实现项目从0到1再到n的爆发式增长。 全书有两条主线。一条是营销思维线,侧重于如何思考,包括:升级行业、创新文化,寻找营销切入点;挖掘品 牌和个人的亮点、“做轻”产品,打造具有互联网营销特色的冷启动项目;突破思维,把实体经济“做虚”,发挥虚拟经济的价值。另一条是营销策略线,侧重于如何行动,包......一起来看看 《冷启动》 这本书的介绍吧!

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具