码迷,mamicode.com
首页 > 其他好文 > 详细

Scala 伴生对象

时间:2015-04-10 20:34:35      阅读:148      评论:0      收藏:0      [点我收藏+]

标签:

Scala 伴生对象


转载时请以超链接形式标明文章原始出处和作者信息及本声明

http://www.blogbus.com/dreamhead-logs/60217908.html


准备涉水Scala的Java程序员请注意,Scala里没有static


在大多数情况下,static真不该是static的。像Scala这样想在面向对象上更进一步的程序设计语言,取消static是一种进取的表现,这样得以保证了其面向对象模型的完整性。好吧,我承认,??有时候,我们还是需要类一级的属性和操作的。在Scala里,我们还是有机会的,这便是伴生对象(Companion Object)的作用。??


下面就是一个伴生对象的例子:

object Companion {
  def show = println("I am a companion")
}
class Companion {
  def shout = Companion.show
}

(Companion.scala)


这个object就是我们所说的伴生对象,如果读过《走进Scala——Singleton》,你会觉得这个伴生对象和Singleton异曲同工,实际上,是这样的。伴生对象本身就是一个Singleton,不同的是,它有一个与之同名的类(这里的class Companion),二者可以相互访问彼此的私有成员。在这里,我们暂且不关心私有成员的相互访问。


编译一下:

scalac Companion.scala


同Singleton一样,我们也得到了两个文件:Companion.class和Companion$.class。我们还可以用javap查看反编译的结果,其中,Companion$.class与之前的Singleton$.class几近相同,这里就省略了。一起来看看Companion.class。

javap -c Companion

输出为:

Compiled from "Companion.scala"
public class Companion {
  public static void show();
    Code:
       0: getstatic     #16                 // Field Companion$.MODULE$:LCompanion$;
       3: invokevirtual #18                 // Method Companion$.show:()V
       6: return

  public void shout();
    Code:
       0: getstatic     #16                 // Field Companion$.MODULE$:LCompanion$;
       3: invokevirtual #18                 // Method Companion$.show:()V
       6: return

  public Companion();
    Code:
       0: aload_0
       1: invokespecial #24                 // Method java/lang/Object."<init>":()V
       4: return
}

反编译 Companion$,javap -c Companion$

Compiled from "Companion.scala"
public final class Companion$ {
  public static final Companion$ MODULE$;

  public static {};
    Code:
       0: new           #2                  // class Companion$
       3: invokespecial #12                 // Method "<init>":()V
       6: return

  public void show();
    Code:
       0: getstatic     #18                 // Field scala/Predef$.MODULE$:Lscala/Predef$;
       3: ldc           #20                 // String I am a companion
       5: invokevirtual #24                 // Method scala/Predef$.println:(Ljava/lang/Object;)V
       8: return
}


因为有了对应的class,object成了伴生对象。从结果可以看出,伴生对象和它对应的类在字节码层面走到了一起(Companion类)。换句话说,在Scala里面的class和object在Java层面里面合二为一,class里面的成员成了实例成员,object成员成了static成员。我们已经知道,这里的static成员只是一个简单的wrapper,封装了实际的操作。

对应到反编译的代码上,我们看到了与object相关的那个static方法——show。因为要构建Companion的实例,所以,生成的代码里有构造函数。此外,class Companion的实例方法shout在字节码层面上也体现到了Companion类里。


至此,我们已经对伴生对象有了一个基本的了解。在Scala的层面上,我们把分属于类和实例分开放置,从代码的组织而言,会更加清晰。在实现层面上,它们都是按照对象处理的(分别用Companion$和Companion),从而达到了对象模型的统一。


注:

C:\WorkSpace6-scala\scala-train\src\com\usoft>scalac -version

Scala compiler version 2.11.4 -- Copyright 2002-2013, LAMP/EPFL


Scala 伴生对象

标签:

原文地址:http://my.oschina.net/xinxingegeya/blog/398729

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!