java调用scala 伴生类_7、scala伴生类和伴生对象

package com.scala.test

object Test {

def main(args: Array[String]): Unit = {

val p1 = new Person

val p2 = new Person

p1.name = "tom"

p2.name = "jerry"

println(p1.name)

println(p2.name)

}

}

class Person {

var name: String = _

def sayName(): Unit = {

println(this.name)

}

}

此时,代码和静态没有一毛钱关系,p1和p2各自为政,都拥有自己特有的name属性。

如果想要让Person类增加一个静态属性age,即age属性是属于类的,即当修改p1对象的age属性,会导致p2对象的age也修改, 同理如果修改p2对象的age属性,那么也会导致p1对象的age遭到修改!

其实这个也好办,在类的内部增加一个对象即可,p1和p2都有这么个属性,这个属性值就是同一个A对象,如下图:

package com.scala.test

object Test {

def main(args: Array[String]): Unit = {

val p1 = new Person

val p2 = new Person

p1.name = "tom"

p1.a.age = 20 // 这里修改age, 会导致p2对象的age也变为20

p2.name = "jerry"

p2.a.age = 50 // 这里修改age, 会导致p2对象的age也变为50 ps:这样算是变相滴实现了静态属性age

println(p1.name + "\t" + p1.a.age)

println(p2.name + "\t" + p2.a.age)

}

}

class Person {

var name: String = _

val a: A.type = A

def sayName(): Unit = {

println(this.name)

}

}

object A {

var age = 10

def sayAge(): Unit = {

println(age)

}

}

如上图,p1对象和p2对象拥有同一个A实例,修改任何一个对象的age,都会影响到另一个对象的age,这样算是间接滴实现了静态,跟java的静态还不太一样,这里只是用了某些手段实现了静态的功能,这个姑且叫"伪静态"吧

但是又有新问题了,可以看出调用时真麻烦,还得这样调用:p1.a.age 和 p2.a.age, 然后尝试想,p1.a.age 就等价于A.age,可以用类名直接调用!然后就接着想如果那个单例对象的名字也叫做Person, 这样以后调用时,直接调用Person.age岂不是更好, 这样看起来更像是"静态调用" ! 于是就有了如下代码:

package com.scala.test

object Test {

def main(args: Array[String]): Unit = {

val p1 = new Person

val p2 = new Person

p1.name = "tom"

Person.age = 20

p2.name = "jerry"

Person.age = 50

println(p1.name + "\t" + Person.age) // 这样调用看起来更像是"静态调用":动态属性用实例调用, 而静态属性用类名调用

println(p2.name + "\t" + Person.age)

}

}

class Person {

var name: String = _

def sayName(): Unit = {

println(this.name)

}

}

object Person {

var age = 10

def sayAge(): Unit = {

println(age)

}

}

上面代码看起来更像是"静态属性"。ps:scala并没有"静态"的概念,只是通过某种手段实现了"静态"的功能。

上面的代码又出现了新问题, java中静态属性,既可以用类名.属性调用,也可以用对象.属性调用, 而上面的代码只能做到用类名.属性,所以还需要增加对象.属性调用方式,如下图:

package com.scala.test

object Test {

def main(args: Array[String]): Unit = {

val p1 = new Person

val p2 = new Person

p1.name = "tom"

p1.setAge(40)

p2.name = "jerry"

p2.setAge(50)

println(p1.name + "\t" + p1.age) // 这样调用看起来更像是"静态调用":动态属性用实例调用, 而静态属性用类名调用

println(p2.name + "\t" + p2.age)

}

}

class Person {

var name: String = _

def sayName(): Unit = {

println(this.name)

}

def setAge(newAge: Int): Unit = {

Person.age = newAge

}

def age(): Int = {

Person.age

}

}

object Person {

var age = 10

def sayAge(): Unit = {

println(age)

}

}

这样看起来跟java的静态好像又近了一步!

总结:

scala中没有"静态"的概念,所谓的"静态"都是通过某种手段模拟出来的,即通过"单例对象"进行了模拟!

一个class和一个object,当两个名字相同时,一个就叫做"伴生类", 另一个叫做"伴生对象"。

可以通过反编译的方式看下"伴生类"和"伴生对象"在底层生成的.class文件, 基本类似于我上面的代码。

暂时可以这么理解:伴生类中写的属性都是动态的,即每个对象都是独有一份,而半生对象中写的属性是静态的,所有的对象共享这个属性。

既然是静态的了,那么调用时建议用"类名.属性"来调用。

静态方法大致也类似于静态属性。

感兴趣的朋友可以自己写一个"伴生类"和"伴生对象",然后反编译出来看看,细细体会下scala为实现"静态"而使用的"巧妙手法"。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值