样例类(case class)
Scala中提供了一种特殊的类,用case class进行声明,中文也可以称作“样例类”。样例类是一种特殊的类,经过优化以用于模式匹配。样例类类似于常规类,带有一个case 修饰符的类,在构建不可变类时,Case类非常有用,特别是在并发性和数据传输对象的上下文中。示例如下:
case class Message(from:String, to:String, content:String)
一个样例类相当于一个JavaBean风格的域对象,带有getter和setter方法,以及构造器、hashCode、equals和toString方法。在创建case class的对象实例时,不需要使用new关键字。
例如,下面的代码是有效的:
val request = Message("北京","上海","高铁");
Scala更喜欢使用不变性。因此,在case类上定义的字段在默认情况下是不可变的,因此不能修改它们。如果一定要想修改case类的字段,可以在声明时使用var关键字来指定。
下面的代码定义了一个简单的样例类:
// 定义一个样例类 case class Stuff(name:String, var age:Int) val s = Stuff("张三",45) // 不需要使用new来实例化 println(s) s == Stuff("张三",45) s == Stuff("张三",43) println(s.name) println(s.age) s.age = s.age + 1 println(s.age)
输出结果如下图所示:
另外,在一个样例类的定义中指定的所有输入参数不需要使用var或val修饰,Scala自动就会使用val修饰。可以从该类的外部访问它。
样例类会自动创建伴生对象。此外,Scala 添加如下四个方法到一个样例类:apply()、toString()、hashCode、equals()和copy()。这些方法使得使用一个样例类更容易。样例类对于创建不可变对象很有用。此外,它们支持模式匹配。
下面是使用case class的示例代码:
// 定义一个case class case class Money(amount:Int=1, currency:String="¥") // 创建类的实例。注意:这里不需要用new关键字来实例化 val defaultAmount = Money() val fifteenYuans = Money(15,"¥") val fifteenYuans = Money(15) val someYuans = Money(currency="¥") val twentyYuans = Money(amount=20,currency="¥") // 使用copy方法构造实例: val tenEuros = twentyEuros.copy(10) val twentyDollars = twentyEuros.copy(currency="USD") // --------------------------------------------------------------- // 定义case类 case class Book(isbn: String) // 注意:这里不需要用new关键字来实例化 val frankenstein = Book("978-0486282114") // 带有参数时,参数是public val类型的 case class Message(sender: String, recipient: String, body: String) val message1 = Message("aa@qq.com", "bb@163.com", "hello?") println(message1.sender) // 输出aa@qq.com message1.sender = "cc@sina.com" // 这一行不会编译 // 拷贝 // 可以简单地使用copy方法创建一个case类实例的浅拷贝。可以改变构造器参数(可选地) case class Message(sender: String, recipient: String, body: String) val message4 = Message("aa@qq.com", "bb@163.com", "good good study") val message5 = message4.copy(sender = message4.recipient, recipient = "cc@sina.com") message5.sender // bb@qq.com message5.recipient // cc@sina.com message5.body // "good good study"
当一个类被声名为case class的时候,scala会帮助我们做下面几件事情:
- 构造器中的参数如果不被声明为var的话,它默认的话是val类型的,但一般不推荐将构造器中的参数声明为var。
- 自动创建伴生对象,同时在伴生对象里实现apply方法,使得我们在使用的时候可以不直接显示地new对象。
- 伴生对象中同样会实现unapply方法,从而可以将case class应用于模式匹配。
- 实现自己的toString、hashCode、copy、equals方法。
除此之此,case class与其它普通的scala类没有区别。
Scala自动为case class定义了伴生对象,也就是object,并且定义了apply()方法负责对象创建,该方法接收与主构造函数相同的参数,并返回一个case class对象。
case class是按结构比较的,而不是按引用比较。例如,在下面的代码中,尽管book1和book2引用不同的对象,但是每个对象的值是相等的:
case class Book(bookName: String, author: String) val book1 = Book("Spark大数据处理", "xinliwei") val book2 = Book("Spark大数据处理", "xinliwei") println(book1 == book2) // 输出值为 true