Scala 一张图带你看懂什么是伴生对象
Posted 健哥说编程
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Scala 一张图带你看懂什么是伴生对象相关的知识,希望对你有一定的参考价值。
不得不说,Scala在数据封装上已经显示出它比Java的便捷。
1、类和对象
本节内容:
类、字段、方法。
1、类、字段和方法
定义一个类:
scala> class Stud{}
defined class Stud
使用new关键字,创建这个类对象:
scala> val stud = new Stud()
stud: Stud = Stud@5add7380
定义成员变量,如果没有使用修饰符号,则默认修饰符号为:public:
scala> class Stud{
| var name=""
| }
defined class Stud
创建这个对象:
scala> val stud = new Stud()
stud: Stud = Stud@4f6a5cc9
scala> stud.name="Jack"
stud.name: String = Jack
scala> println(stud.name)
Jack
成员变量必须要被赋值,否则将编译出错:
scala> class Stud{
| var name:String="" //这儿必须要赋值
| }
defined class Stud
scala> val stud = new Stud();
stud: Stud = Stud@5776a9f8
scala> stud.name="Jery"
stud.name: String = Jery
或是声明变量的具体类型,如果没有声明类型则必须要通过=等于符号赋值,然后通过被赋的值,判断变量的类型:
scala> class Stud{
| var name:String=null;
| }
defined class Stud
scala> val stud:Stud = new Stud();
stud: Stud = Stud@33602729
scala> stud.name="Jerry"
stud.name: String = Jerry
scala> println(stud.name)
Jerry
可以使用private关键字保护成员变量:
scala> class Stud{
| private var name:String="Jack"
| }
defined class Stud
访问私有变量,可以提供些方法:
package cn.wangjian
object Demo01_Object {
//用object定义的main方法用于运行
def main(args: Array[String]): Unit = {
val stud: Stud = new Stud();
stud.setName("Jack");
println("name is:" + stud.getName());
}
class Stud {
private var name: String = "";
def setName(name: String): Unit = {
this.name = name
}
def getName(): String = {
//return关键字可以省略
return this.name
}
}
}
注意:
1、上述中的参数变量name:String为val类型,所以不能再被赋值。
2、return语句可以省略,在scala中,默认最后一个表达式即为返回值。
以下是更简捷的方法:
package cn.wangjian
object Demo02_Field {
def main(args: Array[String]): Unit = {
val stud:Stud = new Stud();
stud.setName("WangJian");
println(stud.getName());
}
//以下是更快捷的方法
class Stud {
private var name: String = null;
def setName(name: String):Unit = this.name = name;
def getName(): String = this.name;
}
}
2、类型推断和分号推断
方法的返回类型,scala可以自行推断:
上面所示,在IDEA中Scala自动推断的返回类型是Int。
尽管Scala可以自动推断类型,但还是建议给出具体的返回类型,正如以下代码所示:
每一行语句最后的分号可以省略,但一行中包含多个语句时,分号则是必须的如:
val name:String = "Jerry";println(name);
3、单例对象
1:Scala更面向对象,所以Scala的成员不允许有静态成员。
2:使用object关键字,用于定义一个单例的对象,而不是使用class关键字。
3:单例类必须要在同一个文件中定义类和类的伴生对象。
4:Scala没有像Java那样的的静态类、静态成员、静态方法。但是Scala提供的object对象。这个Object类似于Java的静态类,它的成员、它的方法,默认都是静态的。
1、object类
示例1:
package cn.wangjian
object Demo03_Object {
def main(args: Array[String]): Unit = {
println(Other.name);//由于Other类的name是静态的,所以可以直接调用
}
//使用Object定义一个类,里面的方法默认都是静态的
object Other{
var name:String="Jack";
}
}
2、伴生对象与单例模式
1:如果有同样一个类与object名称完全一样,则这个类就是object的伴生类,相对的,object就类的伴生对象。
2:如果一个类有伴生对象,这个类,就可以通过object的名称访问到这个类的所有成员,但object不在此类的作用范围内。
所以声明scala单例对象的开过过程如下:
1:声明一个类,并使用private关键字,不允许其他对象实例化此类。即:class XXX private { ... }
2:声明伴生对象,并使用var声明伴生类的实例变量,并可以使用private关键字修饰。然后建议再创建一个方法叫instance()或apply()返回这个成员变量的引用。
3:然后就可以在其他的方法中通过伴生对象引用单一伴生类的实例了。
package cn.wangjian
/**
* 测试单例对象
*/
object Demo04_Singletone {
def main(args: Array[String]): Unit = {
val singletone: Singletone = Singletone.apply();
singletone.setName("Jack");
println(singletone.getName());
}
//定义类,将这个类定义成private,定义成private以后,其他对象将不能实例化这个对象,即不能new
class Singletone private {
private var name: String = _;
private var age: Int = _;
def setName(name: String): Unit = this.name=name;
def getName(): String =this.name
}
//定义object对象
object Singletone {
/*这儿使用_下划线,表示赋值为变量的默认值,对于int默认值为0
对于引用类型默认值为null,在其他运算中,下划线,表示当前对象自己*/
private var self: Singletone = _
def apply(): Singletone = {
if (self == null) {
self = new Singletone()
self
} else {
self
}
}
}
}
一张图看懂Scala伴生对象实现的单例模式:
3、Scala应用程序
Scala应用程序是指包含main方法的程序。
1:只有使用object关键字声明的对象(类),才可以拥有main方法。
2:Scala代码中,默认被导入的包是:java.lang.*及scala._两个包和名为predef单例对象的所有成员。
即:
import scala._
import java.lang._
import scala.Predef._
3:在Predef中定义了包含Map,Set,String等等对象,所以在Scala程序中,可以直接使用。
4:在Predef中定义了很多有用的方法,如println就定义在Predef中。当调用println时,实际调用的是Predef.println方法。转而又调用了Console.println(..)方法。
5:Scala的类或对象可以放到任意命名的scala文件中。但还是建议参考Java的做法,将类放到同名的文件中。
6:scalac用于编译一个scala的源文件。
1、使用scalac编译scala源文件
对于开发完成的scala源文件,可以使用scala将它编译成java代码
以下是一个Scala的源文件:
Hello.scala文件:
package cn
object Hello{
def main(args:Array[String]):Unit={
println("Hello")
}
}
然后使用scala编译上面的源代码:
D:\a>scalac Hello.scala
直接带包编译到目录下的文件为:
D:\a\cn
两个.class的java文件
如果对内部结构感兴趣,可以使用jdecompiler查看上面的字节码的源代码。
使用scala命令,运行编译的程序:
D:\a>scala cn.Hello
Hello
本质上来讲,可以使用scala命令直接运行一个.scala源文件,但这个源文件不能声明包:
所以,以下类可以直接通过scala运行,因为它没有声明包:
object Hello{
def main(args:Array[String]):Unit={
println("HelloWorld")
}
}
而以下类无法通过scala命令直接运行,必须要使用scalac编译以后才可以运行:
因为它有包:
package cn
object Hello{
def main(args:Array[String]):Unit={
println("Hello")
}
}
2、APP类
也可以直接使用app类开发应用程序,APP类中已经包含了main函数,直接继承App类然后开发需要的代码即可:
package cn.wangjian
/**
* 另一种开发APP的方法
*/
object Demo05_App extends App {
println("参数的个数:"+args.length)
for(arg<-args){
println(arg)
}
println("遍历完成")
}
以上是关于Scala 一张图带你看懂什么是伴生对象的主要内容,如果未能解决你的问题,请参考以下文章
通过 Java 反射找到 Scala 类型的伴生对象的可靠方法是啥?