Scala中的说话特点是如何实现的(2)

    添加时间:2013-5-20 点击量:

    上篇博文的末尾留了三个题目,如今自问自答一下。


    在Scala中被声明为val的v4为什么在反编译的Java中不是final的呢?


    在办法中声明局部变量时,若是用Scala的val关键字(或者是Java中的final)来润饰变量,则代表着此变量在赋过初始值之后不成以再被从头赋值。这个val或者final只是给编译器用的,编译器若是发明你给此变量从头赋值会抛失足误。


    而bytecode不具备表达一个局部变量是immutable的才能,也就是说对于JVM来说,不存在不成变的局部变量这个概念。所以v4在反编译之后,就和通俗的局部变量无异了。


    在Scala中被声明为val的v2为什么在反编译的C#中不是readonly的呢?


    这是个挺tricky的题目,我试着申明一下。Scala .NET是基于IKVM实现的,IKVM可以把Java bytecode翻译为CIL。 所以Scala编译为CIL的过程实际是如许的:


    Scala —–Scala编译器—–> bytecode —–IKVM—–> CIL


    Scala编译器编译出的bytecode实际是用final润饰了v2的,然则bytecode中的final和CIL中的initonly(对应C#的readonly)是不一样的。


    Java中,final实例变量定义的时辰,可以先声明,而不给初值,然后我们可以在任何一个办法中给它赋初值。这供给了更大的灵活性,一个Java类中的final成员可以依对象而不合,却对峙其immutable的特点。


    而CIL的initonly则要严格一点,CLI标准(ECMA-334)如许描述:



    initonly marks fields which are constant after they are initialized. These fields shall only be mutated inside a constructor. If the field is a static field, then it shall be mutated only inside the type initializer of the type in which it was declared. If it is an instance field, then it shall be mutated only in one of the instance constructors of the type in which it was defined. It shall not be mutated in any other method or in any other constructor, including constructors of derived classes.



    可见,一个initonly的成员,不是随便在哪儿都可以赋初值的。因为这点不合IKVM就没有直接把final翻译成initonly。若是想让v2在C#代码中变成readonly的,可以给IKVM加上strictfinalfieldsemantics这个参数。


    为什么反编译出来的C#代码中的实例级公创办法都是标有override的呢?


    这个题目还没搞熟悉打听。


    然则有个有趣的现象,若是用Scala .NET来编译Scala源码,编译出的实例级办法都是标有override的;而若是先把Scala代码编译为.class然后再用IKVM把.class文件转换为CIL的话,办法例是标有virtual的。我猜这可能和Java中的办法默认是可以被overirde的有关。


    下面开端正文,前面填坑用了不少篇幅,所以此次只解析一个说话特点:Scala中的constructor。


    Constructor


    Scala中可以在声明class的同时声明一个constructor,比如如许:







    1
    
    2
    3

    我们永远不要期待别人的拯救,只有自己才能升华自己。自己已准备好了多少容量,方能吸引对等的人与我们相遇,否则再美好的人出现、再动人的事情降临身边,我们也没有能量去理解与珍惜,终将擦肩而过。—— 姚谦《品味》
    分享到: