Class&Object
由于Scala没有静态方法和静态类,通过object去定义静态方法或者静态对象。当object和Class放在一个文件中的时候称该object为当前Class的半生对象。
单例类
单例类使用object修饰,所有声明在object中的方法都是静态方法,类似于java中声明的工具类的作用。
object HelloUtil {
def sayHello(name:String):Unit={
println("hello~"+name)
}
}
类
class User {
var id:Int = _
var name:String = _
var age:Int = _
def this(id:Int,name:String,age:Int){
this()
this.id=id
this.name=name
this.age=age
}
}
必须要求在构造方法的第一行显示调用this(),其中_表示参数赋值为默认值
- def this(参数)定义构造器
class User {
var id:Int = _
var name:String = _
var age:Int = _
def this(age:Int){
this()
this.age=age
}
def this(id:Int,name:String,age:Int){
this(age)
this.name=name
this.id=id
}
}
使用该种方式声明构造类似于java编程,但是要求在构造的第一行必须显示调用this方法。这本质上是因为如上声明的类,等价声明了class User(){} 类似使用this()调用构造器。
- 类上声明(默认构造器)
一旦类上声明了参数,在使用this声明其他的构造器的时候,必须在第一行调用类上的构造器。
class User (var id:Int,var name:String,var age:Int){
def this(age:Int){
this(id:Int,name:String,age:Int)
this.age=age
}
def this(id:Int,name:String,age:Int){
this(age)
this.name=name
this.id=id
}
伴生对象
如果类和object在一个Scala文件中,则称为object User是class User的伴生对象,使用伴生对象可以方便的创建对象,只需要覆盖对应的apply方法,如下:
class User02(id:Int,name:String,age:Int) {
override def toString:String = {
this.id+" "+this.name+" "+this.age
}
}
object User02{
def apply(id: Int, name: String, age: Int): User02 = new User02(id, name, age)
}
var user=User02(1,"zhangsan",18)//等价new User02(1,"zhangsan",18)
这里可以理解apply是一个工厂方法,该方法的作用是生产User实例对象。
使用unapply方法能够将对象中的一些属性反解出来
object User02{
def unapply(user0: User02): Option[(Int, String, Int)] = {
Some(user0.id,user0.name,user0.age)
}
def apply(id: Int, name: String, age: Int): User02 = new User02(id, name, age)
}
var user2 = User02(1,"zhangsan",20)
var u3 = new User02(2,"zhangsan",15)
var User02(id:Int,name:String,age:Int)=u3
println(id+" "+name+" "+age)
注意一个伴生对象中只能有一个unapply方法,这不同于apply方法,以为apply方法可以有多个。
抽象类
abstract class Animal (var name:String){
def eat():Unit={
println("animal can eat...")
}
def sleep():String
}
Trait(接口)
trait Speakable {
def speek():Unit
}
trait Flyable {
def fly():Unit
}
继承&实现
写一个Dog类继承Animal并且实现Speakable特质。
class Dog(name:String) extends Animal (name:String) with Speakable {
override def sleep(): String = {
"im a dog I sleep 8 hours"
}
override def speek(): Unit = {
println("wang wang ~~")
}
override def eat():Unit = {
println("啃骨头")
}
}
object Dog{
def apply(name: String): Dog = new Dog(name)
}
Trait动态植入
假如说现在有一个Bird继承自Animal,在使用的时候会发现该类需要具备Flyable的功能,可以写法如下:
class Bird (name:String) extends Animal (name:String){
override def sleep(): String = {
"bird is sleeping"
}
}
def main(args: Array[String]): Unit = {
var b = new Bird("麻雀") with Flyable{
override def fly(): Unit = {
println("小鸟会飞")
}
}
b.fly()
}
1.在覆盖有实现的方法必须添加override; 2.一个类只能继承一个类with多个trait 例如:Class A extends B with C with D{}
self
等价于this关键字,在this出现混淆的时候使用self给this关键字起别名。
class User {
self =>
var id:Int = _
var name:String = _
var age:Int = _
def this(age:Int){
this(id:Int,name:String,age:Int)
self.age=age
}
def this(id:Int,name:String,age:Int){
this(age)
self.name=name
self.id=id
}
}
- Trait强制混合
以下案例就是要求所有Flyable的子类必须实现Bird接口。
trait Flyable {
this:Bird =>
def fly():Unit={
println(this.name+"可以飞!")
}
}
trait Bird{
def name : String
}
class FlyFish(n:String) extends Flyable with Bird {
override def name: String = this.n
}
Case class
case class就像常规类,case class适用于对不可变数据进行建模。
case class UserCase(id:Int,name:String) {
def sayHi():Unit = {
println(this)
}
}
var uc1 = new UserCase(1,"zhangsan")
var uc2 = UserCase(1,"zhangsan")
与普通的class不同的是,CaseClass创建的对象==比较的是对象的内容,其次CaseClass的所有属性都是只读,不允许修改。通常用于只读数据的建模。可以简单的使用copy来实现两个对象间的值传递
var uc1= new UserCase(1,"zhangsan")
var uc2= uc1.copy(id=uc1.id,name=uc1.name)
uc2.sayHi()