scala中的伴生类和伴生对象

2023-04-27 18:52:19 浏览数 (1)

伴生类和伴生对象

设计初衷

由于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中伴生类&伴生对象的语法如下:

代码语言:javascript复制
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一个对象,使用案例如下:

代码语言:javascript复制
object AssociatedDemo{

  def apply():AssociatedDemo = new AssociatedDemo();

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

    // 变量复制,直接可以实例化对象,不需要再new了

    val ad1 = AssociatedDemo();

  }

}
demo

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

代码语言:javascript复制
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如下:

代码语言:javascript复制
case class Message(sender: String, recipient: String, body: String)

val message2 = Message("[jorge@catalonia.es](mailto:jorge@catalonia.es)", "[guillaume@quebec.ca](mailto:guillaume@quebec.ca)", "Com va?")

val message3 = Message("[jorge@catalonia.es](mailto:jorge@catalonia.es)", "[guillaume@quebec.ca](mailto:guillaume@quebec.ca)", "Com va?")

val messagesAreTheSame = message2 == message3  // true

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

case object

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

代码语言:javascript复制
case class CaseClass2(a:Int) extends SuperTrait         // Case class  

case object CaseObject extends SuperTrait               // Case object
Match匹配

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

代码语言:javascript复制
// 定义案例类

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"

  }

}

本文为从大数据到人工智能博主「xiaozhch5」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://cloud.tencent.com/developer/article/2275265

0 人点赞