Scala学习笔记(9)——面向对象(二)
一、单例对象(伴生对象)
Scala语言是完全面向对象的语言,所以并没有静态的操作(即在Scala中没有静态的概念)。但是为了能够和Java语言交互(因为Java中有静态概念),就产生了一种特殊的对象来模拟类对象,该对象为单例对象。若单例对象名与类名一致,则称该单例对象这个类的伴生对象,这个类的所有“静态”内容都可以放置在它的伴生对象中声明。
1.单例对象语法
1)基本语法
object Person{
val country:String="China"
}
2)说明
(1)单例对象采用 object 关键字声明
(2)单例对象对应的类称之为伴生类,伴生对象的名称应该和伴生类名一致。
(3)单例对象中的属性和方法都可以通过伴生对象名(类名)直接调用访问。
2. apply 方法
在伴生对象中可以定义一个apply方法,Scala底层对apply方法有特殊支持,使得Student11(“bob”, 19)就代表调用apply方法
object Test11_Object {
def main(args: Array[String]): Unit = {
val student2 = Student11.apply("bob", 19)
student2.printInfo()
val student3 = Student11("bob", 19)
student3.printInfo()
}
}
// 定义类,加上private关键字将构造器方法私有化
class Student11 private(val name: String, val age: Int){
def printInfo(){
println(s"student: name = ${name}, age = $age, school = ${Student11.school}")
}
}
// 伴生对象
object Student11{
val school: String = "atguigu"
// 定义一个类的对象实例的创建方法
def apply(name: String, age: Int): Student11 = new Student11(name, age)
}
二、特质(Trait)
Scala 语言中,采用特质 trait(特征)来代替接口的概念,也就是说,多个类具有相同的特质(特征)时,就可以将这个特质(特征)独立出来,采用关键字 trait 声明。
Scala 中的 trait 中即可以有抽象属性和方法,也可以有具体的属性和方法,一个类可以混入多个特质。这种感觉类似于 Java 中的抽象类。
Scala 引入 trait 特征,第一可以替代 Java 的接口,第二个也是对单继承机制的一种补充
1.特质的基本语法
一个类具有某种特质(特征),就意味着这个类满足了这个特质(特征)的所有要素,所以在使用时,也采用了 extends 关键字,如果有多个特质或存在父类,那么需要采用 with关键字连接。
1)基本语法:
没有父类:class 类名 extends 特质 1 with 特质 2 with 特质 3 …
有父类:class 类名 extends 父类 with 特质 1 with 特质 2 with 特质 3…
2)说明
(1)特质可以同时拥有抽象方法和具体方法
(2)一个类可以混入(mixin)多个特质
(3)所有的 Java 接口都可以当做 Scala 特质使用
(4)动态混入:可灵活的扩展类的功能
(4.1)动态混入:创建对象时混入 trait,而无需使类混入该 trait
(4.2)如果混入的 trait 中有未实现的方法,则需要实现
// 动态混入
val studentWithTalent = new Student14 with Talent {
override def dancing(): Unit = println("student is good at dancing")
override def singing(): Unit = println("student is good at singing")
}
特质和抽象类的区别
1.优先使用特质。一个类扩展多个特质是很方便的,但却只能扩展一个抽象类。
2.如果你需要构造函数参数,使用抽象类。因为抽象类可以定义带参数的构造函数,而特质不行(有无参构造)。
2. 特质自身类型
通过特质自身类型可实现依赖注入的功能。
object Test16_TraitSelfType {
def main(args: Array[String]): Unit = {
val user = new RegisterUser("alice", "123456")
user.insert()
}
}
// 用户类
class User(val name: String, val password: String)
trait UserDao {
//特质自身类型
_: User =>
// 向数据库插入数据
def insert(): Unit = {
println(s"insert into db: ${this.name}")
}
}
// 定义注册用户类
class RegisterUser(name: String, password: String) extends User(name, password) with UserDao
三、扩展
1.类型检查和转换
obj.isInstanceOf[T]:判断 obj 是不是 T 类型。
obj.asInstanceOf[T]:将 obj 强转成 T 类型。
classOf 获取对象的类名。
2.枚举类和应用类
(1) 枚举类:需要继承 Enumeration
object Test {
def main(args: Array[String]): Unit = {
println(Color.RED)
} }
// 枚举类
object Color extends Enumeration {
val RED = Value(1, "red")
val YELLOW = Value(2, "yellow")
val BLUE = Value(3, "blue")
}
(2) 应用类:需要继承 App
可直接运行,App中自带main方法
// 应用类
object Test20 extends App {
println("xxxxxxxxxxx");
}
3.Type 定义新类型
使用 type 关键字可以定义新的数据数据类型名称,本质上就是类型的一个别名
object TestApp extends App {
type MyString = String
val a: MyString = "abc"
println(a)
}
上一篇: 详解函数的调用过程