单例对象
要点:
在scala当中,不会像java那样提供static的关键字用于创建一个单例对象。但我们可以通过object这个关键字来定义一个单例对象,在object块里面的成员变量与方法都是静态的。但要注意的是:在java当中,static的静态成员变量、静态块是在类加载的时候就被执行了,而在scala当中,只有第一次调用的时候才会执行。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19object SingletonClass {
private var num = 0;
def getNum = {
num += 1;
num
}
}
object Main {
def main(args: Array[String]) {
println(SingletonClass.getNum)
println(SingletonClass.getNum)
}
}
out :
1
2
伴生对象
概念:
当一个类定义为class A,则对应的object A就是它的伴生对象。它能访问伴问伴生对象当中的任意成员变量,即使是private的也可以。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23//伴生对象
object SingletonClass {
private var num = 0;
def getNum = {
num += 1;
num
}
}
//伴生类
class SingletonClass {
private var id = SingletonClass.getNum;
private var num = 0;
def getNum(num : Int) = {
this.num += num
}
}
注意:
伴生对象通常用于作为伴生类的静态成员变量的封装区域。
apply方法讲解
object中:
当使用伴生对象来生成对象时,就会调用其apply方法class中:
当直接使用new clazz的方式来创建对象的时候是不会调用类当中的apply方法的,只有当使用创建了的对象A,直接调用A()就能调用类当中的apply方法1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29class ArrApply{
def apply() = {
println("print from class")
//new ArrApply()
}
def doSomething() = {
println("doSomething")
}
}
object ArrApply{
def apply() = { //=号不能少,少了doSomethin方法调用的地方会报错,还没找到原因
println("print from object")
new ArrApply()
}
}
object ApplyOps {
def main(args: Array[String]) {
val arr = ArrApply() //通过伴生对象创建一个伴生类对象
arr.doSomething()
val array = new ArrApply()
array() //调用类的apply方法
}
}
scala继承
它的使用方法与java类似,只是在重写的时候要使用override关键字。但在java当中,是在子类的构造器中调用父类的构造器的,而scala中,是在定义子类的时候填满父类的主构造方法1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49class ExtendClass(name : String) {
val school = "GDUT"
def showInfo : String = {
school
}
def showName : String = { //当子类没有重写时,即使调用了changeName也返回构造值,因为这里返回的是父类的name,而修改的只是子类的name而已
name
}
override def toString = {
"in gdut"
}
}
class Student(var name : String) extends ExtendClass(name) {
override val school = "gdut"
override def showInfo : String = {
"a boy in " + school
}
def changeName(name : String) = {
this.name = name
}
override def showName : String = {
name
}
}
object ExtendOps {
def main(args: Array[String]) {
val student = new Student("xiaoming")
println(student.toString)
println(student.showInfo)
student.changeName("xiaodong")
println(student.showName)
}
}
抽象类
与java类似,在scala当中也是通过abstract关键字来定义一个抽象类,对于抽象类当中的字段,如果没有赋值则是抽象的成员变量,对于方法如果没有具体的实现则为抽象方法。但要注意的是,在java当中抽象方法是要使用abstract来修饰的,但在scala当中,abstract只能用于修饰class。如果一个类不是抽象类,那么它的成员变量是一定要进行赋值的,可以是具体的值,也可以是一个占位符。而使用占位符只能是成员变量类型为var的情况。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24abstract class AbstractClass {
var name : String = "xiaoming"
var age : Int
def teach()
}
class MathTeacher extends AbstractClass {
override var age = 22
override def teach() = {
print("math teacher")
}
}
object AbstractOps {
def main(args: Array[String]) {
val teacher = new MathTeacher();
teacher.teach()
}
}
scala当中的接口-trait
在scala当中的trait与java中的interface类似,但trait的功能更为强大,它能够有方法的具体实现(JDK1.8也可以通过default关键字来提供)。在使用triat的实现类的时候,我们还可以通过with关键字来给该对象混入其它的triat实现,这相当于一个动态的extends操作。在java当中多实现是用,来分割的,但scala当中是使用with1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42trait TriatClass {
def log()
}
trait OtherTriat {
def consoleLog(): Unit ={
println("console log...")
}
}
trait TriatClassImpl extends TriatClass{
override def log(): Unit ={
println("triatclassimpl...")
}
}
class ConcreteLog extends TriatClass {
override def log(): Unit ={
print("concretelog...")
}
}
object TriatOps {
def main(args: Array[String]) {
val log = new ConcreteLog
log.log()
val logger = new ConcreteLog with TriatClassImpl
logger.log()
val console = new ConcreteLog with OtherTriat //混入其它triat
console.log()
console.consoleLog()
}
}