Scala学习笔记-伴生对象于孤立对象
2016-05-11 09:09
519 查看
Scala-伴生对象于孤立对象
![](http://img.blog.csdn.net/20160509095250288)
Scala虽然是基于JVM构建的,但与Java还是有很多区别,其实一个重要的区别是Scala比Java更面向对象(纯面向对象),最明显的用例是scala中所有的操作符都是方法(操作符面向的使用者是对象)。
伴生对象/孤立对象也是scala作为纯面向对象语言的一种体现。
使用时,它给人的感觉类似下面的代码
所以,我们可以向下面的方式访问
这会给人以上的错误,但实际情况并非如此,此处的Test实际上是一个对象(全局单例),看下面的例子
在REPL中运行结果如下:
到此,总结一下,对于
scala源码
编译后的Java代码
虚构类:
伴生类
从上面有缺陷的反编译代码中我们可以看出,在Test上的所有调用最后都作用到单例对象
调入入口(Test.xxxx)
↓
伴生类(static方法)
↓
虚构类(单例对象MODULE$)
伴生类源码与伴生对象源码必须在同一个
伴生类与伴生对象名称必须相同
下面为孤立对象Test创建一个伴生类
有了前面的基础,直接分析编译后的源码
虚构类:
伴生类:
从上述反编译后的代码来看,对于同时具有伴生类和伴生对象的scala代码,编译后,仍然是两个class文件,在伴生对象中的属性和方法仍然按照前面的规则被编译,但在伴生类中的属性和方法有所不同,它被放到伴生类的class文件中,并且是非静态的,这就意味着这些属性和方法是实例相关的,这是符合预期的。
那么,对于Test来说
对象
都为true,因为此处Test被指向了全局唯一的单例对象
总结一下
伴生对象的属性、方法仍指向全局单例对象
伴生类的属性、方法被定义为对象相关的。
伴生对象通常被用在单例对象或工具方法的容器
Scala虽然是基于JVM构建的,但与Java还是有很多区别,其实一个重要的区别是Scala比Java更面向对象(纯面向对象),最明显的用例是scala中所有的操作符都是方法(操作符面向的使用者是对象)。
伴生对象/孤立对象也是scala作为纯面向对象语言的一种体现。
孤立对象
先看一个例子object Test{ var a = "helloworld" def helloworld(): Unit = { println("helloworld") } }
使用时,它给人的感觉类似下面的代码
public class Test { public static String a = "helloworld"; public static void helloworld() { System.out.println("helloworld"); } }
所以,我们可以向下面的方式访问
a字段或
helloworld()方法
Test.a Test.helloworld()
这会给人以上的错误,但实际情况并非如此,此处的Test实际上是一个对象(全局单例),看下面的例子
object Test{ var a = "helloworld" def helloworld(): Unit = { println("helloworld") } def main(args: Array[String]) { println(Test) } }
在REPL中运行结果如下:
D:\> scalac Test.scala D:\> scala Test Test$@3eb25e1a D:\>
到此,总结一下,对于
object Test{...},我们在使用
Test.field或
Test.method时,
Test实际上是一个全局单例的对象,而不一个类,下面通过反编译的class文件看一下具体细节
scala源码
object Test{ var a = "helloworld" def helloworld(): Unit = { println("helloworld") } }
编译后的Java代码
虚构类:
import scala.Predef.; public final class Test$ { public static final MODULE$; private String a; static { new (); } public String a() { return this.a; } public void a_$eq(String x$1) { this.a = x$1; } public void helloworld() { Predef..MODULE$.println("helloworld"); } private Test$() { MODULE$ = this; this.a = "helloworld"; } }
伴生类
public final class Test { public static void helloworld() { Test..MODULE$.helloworld(); } public static void a_$eq(String paramString) { Test..MODULE$.a_$eq(paramString); } public static String a() { return Test..MODULE$.a(); } }
从上面有缺陷的反编译代码中我们可以看出,在Test上的所有调用最后都作用到单例对象
MODULE$上,整个逻辑机构如下
调入入口(Test.xxxx)
↓
伴生类(static方法)
↓
虚构类(单例对象MODULE$)
伴生对象
带有伴生类的孤立对象叫做伴生对象,伴生类与伴生对象有如下关系:伴生类源码与伴生对象源码必须在同一个
.scala文件中
伴生类与伴生对象名称必须相同
下面为孤立对象Test创建一个伴生类
import scala.beans.BeanProperty
class Test{
@BeanProperty var name = "zhangsan"
def func1() {
println("func1")
}
}
object Test{ var a = "helloworld" def helloworld(): Unit = { println("helloworld") } }
有了前面的基础,直接分析编译后的源码
虚构类:
import scala.Predef.; public final class Test$ { public static final MODULE$; private String a; static { new (); } public String a() { return this.a; } public void a_$eq(String x$1) { this.a = x$1; } public void helloworld() { Predef..MODULE$.println("helloworld"); } private Test$() { MODULE$ = this; this.a = "helloworld"; } }
伴生类:
public class Test { private String name = "zhangsan"; public static void helloworld() { Test..MODULE$.helloworld(); } public static void a_$eq(String paramString) { Test..MODULE$.a_$eq(paramString); } public static String a() { return Test..MODULE$.a(); } public String name() { return this.name; } public void name_$eq(String x$1) { this.name = x$1; } public void setName(String x$1) { this.name = x$1; } public void func1() { Predef..MODULE$.println("func1"); } public String getName() { return name(); } }
从上述反编译后的代码来看,对于同时具有伴生类和伴生对象的scala代码,编译后,仍然是两个class文件,在伴生对象中的属性和方法仍然按照前面的规则被编译,但在伴生类中的属性和方法有所不同,它被放到伴生类的class文件中,并且是非静态的,这就意味着这些属性和方法是实例相关的,这是符合预期的。
那么,对于Test来说
val test1 = new Test val test2 = new Test test1 != test2
对象
test1与
test2是不同的示例,但是
Test.equals(Test) Test == Test
都为true,因为此处Test被指向了全局唯一的单例对象
MODULE$。
总结一下
伴生对象的属性、方法仍指向全局单例对象
MODULE$
伴生类的属性、方法被定义为对象相关的。
伴生对象通常被用在单例对象或工具方法的容器
相关文章推荐
- IDEA设置Java类注释
- Andrdoid中对应用程序的行为拦截实现方式之----从底层C进行拦截
- muSnoitanibmoC.39
- 表单中Readonly和Disabled的区别
- Linux自启动执行命令
- JDBC学习笔记(10)——调用函数&存储过程
- javascript简单判断输入内容是否合法的方法
- Nginx负载均衡+监控状态检测
- Caffe研究实践 一 ------环境搭建
- Scrum 项目 3.0
- 【代码笔记】iOS-评分,支持我们
- 341. Flatten Nested List Iterator
- 【代码笔记】评分,支持我们
- Spring boot + maven + jetty9在提交表单的时候出现Form too large
- C盘空间不足处理
- ubuntu系统google配置hosts
- ecshop二次开发--优惠活动
- 线程
- VGA练习之图像的动态显示(后续)
- Rotate Image