[Scala] 伴生类和伴生对象

愿天堂没有BUG

共 3297字,需浏览 7分钟

 ·

2021-10-12 13:45

伴生类和伴生对象

设计初衷

由于static定义的类和对象破坏了 面向对象编程的规范完整性,因此scala 在设计之初就没有static关键字概念,类相关的静态属性都放在伴生对象object中。

简单理解:object就是java中的static部分,定义的是类中静态属性。

概念

当同一个文件内同时存在object xclass x的声明时:

  • 我们称class x称作object x伴生类

  • object x称作class x伴生对象

其中伴生类和伴生对象需要同名。

在Scala里,类和伴生对象之间没有界限——它们可以互相访问彼此的private字段和private方法。

编译方式

在编译时,伴生类object x被编译成了x.class

而伴生对象object x被编译成了x$.class

创建语法

伴生对象中的属性可以直接使用类名进行调用;伴生类中的属性,需要先实例化对象,才能够进行调用。

没有class,只有object则是单例模式类。

scala中伴生类&伴生对象的语法如下:

class AssociatedDemo {
val a:Int = 10;
var b:Int = 2;
}

object AssociatedDemo{
val object_v1:String = "变量1";

def main(args: Array[String]): Unit = {
// 注:只有伴生对象中可以定义主函数,类似于static修饰
println("伴生对象变量:" + AssociatedDemo.object_v1);
println("伴生类变量:" + (new AssociatedDemo()).a);
}
}
复制代码

输出结果:

伴生对象变量:变量1

伴生类变量:10

apply()

apply()是一个语法糖,直接调用类(对象)名称时候,默认执行的是该类(对象)的apply()方法。

目的是为了适应函数式编程的编码规范,可以在伴生对象的apply()中new一个对象,使用案例如下:

object AssociatedDemo{
def apply():AssociatedDemo = new AssociatedDemo();
def main(args: Array[String]): Unit = {
// 变量复制,直接可以实例化对象,不需要再new了
val ad1 = AssociatedDemo();
}
}
复制代码

demo

class apply() & object apply()的代码案例如下:

class AssociatedDemo {
// class中的apply()方法
def apply(param:String){
println("class apply method called:" + param)
}
}

object AssociatedDemo{
// object中的apply()方法
def apply(param:String){
println("object apply method called:" + param)
}

def main(args: Array[String]): Unit = {
// class 的apply()
val ad2 = new AssociatedDemo();
ad2("AAA")
ad2("BBB")

// object 的apply()
AssociatedDemo("CCC")
AssociatedDemo("DDD")
}
}
复制代码

Demo执行结果

class apply method called:AAA

class apply method called:BBB

object apply method called:CCC

object apply method called:DDD

case class

案例类(case class)和普通类本质没有不同,适合用于属性不可变的类。

case class中默认有apply()来负责对象的创建,不需要new来实例化。

类似于Java 开发中的entity类,属于一种特殊的类,其中属性不可变,且均为public。

定义方法

案例类在比较的时候是按值比较而非按引用比较,Demo如下:

case class Message(sender: String, recipient: String, body: String)

val message2 = Message("jorge@catalonia.es", "guillaume@quebec.ca", "Com va?")
val message3 = Message("jorge@catalonia.es", "guillaume@quebec.ca", "Com va?")
val messagesAreTheSame = message2 == message3 // true
复制代码

尽管message2message3引用不同的对象,但是他们的值是相等的,所以message2 == message3true

case object

没有参数的case类将被声明为case对象而不是case类。默认情况下,case对象是可序列化的。

case class CaseClass2(a:Int) extends SuperTrait         // Case class  
case object CaseObject extends SuperTrait // Case object
复制代码

Match匹配

case class 和 case object可以和match配合使用,Demo如下:

// 定义案例类
abstract class Notification
case class Email(sender: String, title: String, body: String) extends Notification
case class SMS(caller: String, message: String) extends Notification
case class VoiceRecording(contactName: String, link: String) extends Notification

// match匹配对象类型
def showNotification(notification: Notification): String = {
notification match {
case Email(sender, title, _) => "Email"
case SMS(number, message) => "SMS"
case VoiceRecording(name, link) => "VoiceRecording"
}
}
复制代码

参考资料

  1. Scala之:伴生对象与静态概念 - 掘金 (juejin.cn)

  2. 《Scala程序设计:Java虚拟机多核编程实战》

  3. 案例类(Case Classes) | Scala Documentation (scala-lang.org


作者:好奇的小黑
链接:https://juejin.cn/post/7016991894408757262
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。



浏览 16
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报