[Scala] 伴生类和伴生对象

伴生类和伴生对象

设计初衷

由于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("[email protected]", "[email protected]", "Com va?")
val message3 = Message("[email protected]", "[email protected]", "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)

猜你喜欢

转载自juejin.im/post/7016991894408757262