Scala的面向对象
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Scala的面向对象相关的知识,希望对你有一定的参考价值。
1.scala的类
(1)类的成员
class Student {
//使用var定义一个可变的成员变量
var age=18
//使用val定义一不可变的成员变量
val name="zy"
//定义一个私有化成员变量(伴生对象仍然可以访问)
private var id=1001
//定义一个私有化成员变量(伴生对象也不可以访问)
private[this] val address="anhui"
//定义一个成员方法
def running(): Unit ={
println(this.name+"跑~")
}
}
注意点:
? - 在scala中声明类不要指定public,scala的文件名可以与类名不同。
? - 成员属性是否可以修改,取决于是否使用val修饰
? - 成员方法和属性能不能被访问,取决于修饰符,public(默认),private
(2)类的构造器
//在类上声明的是主构造器
class Student(val name:String,val age:Int) {
//使用this为方法名,这个是辅助构造器
def this(name:String,age:Int){
this(name,age)
}
}
主构造器的注意点:
? - 在类上定义的构造器称为主构造器
? - 主构造器包含了整个所有的类的代码块,所以,默认的定义的类中的所有能执行的代码都会执行
? - 主构造器中的参数如果没有使用任何修饰符,默认的就是 private[this] val
? - 主构造器中的参数如果使用val或者var修饰,就相当于一个普通的成员变量
辅助构造器的注意点:
? - 当主构造器被class private Student()修饰了,可以使用辅助构造器创建该类对象
? - 辅助构造器必须使用def修饰,并且方法名为this
? - 辅助构造器中的参数不能使用var或者val 修饰
? - 辅助构造器中的第一行代码必须是:调用其他的构造器
(3)类的私有化
//使用private修饰主构造器,表示私有化类
class Student private(val name: String, val age: Int) {
def this(name: String, age: Int) {
this(name,age)
}
}
//使用 private[this]私有化类
class Person private[this](val name: String, val age: Int) {
}
注意点:
? - 被private修饰的类,被私有化,不能其他类不能创建该类实例,但是伴生对象可以
? - 如果想让伴生对象都不能创建该类的实例,可以使用:class private[this]
? - 当主构造器被class private Student()修饰了,可以使用辅助构造器创建该类对象
??
2.伴生对象
?在scala的类中,与类名相同的单例对象叫做伴生对象。
? 特点:(假设现在有一个类:class Student ,和一个伴生对象:object Student)
? ? - class Student是object Student的伴生类
? ? - object Student是class Student的伴生对象
? ? - 类和伴生对象之间可以相互访问私有的方法和属性
? ? - 伴生类和伴生对象的名称相同
例:
//使用private修饰主构造器,表示私有化类
class Student private {
private val name="zs"
private val age=18
}
object Student{
//在伴生对象中创建私有化类的对象
val student=new Student()
//在伴生对象中访问私有化的属性
val name=student.name
val age=student.age
}
单例对象:
单例对象表示,被object修饰,但是没有自己的伴生类。
例:
object person{
val name="zs"
val age=18
}
特点:
? - scala 语言并不支持静态成员,没有静态方法和静态字段,Scala 通过单例对象 object 来解决
? - 单例对象中的所有成员和方法都是static的
? - 单例对象它本身就是一个单例,(因为不需要去 new)
apply方法
? 在讲集合和数组的时候,可以通过 val intList=List(1,2,3)这种方式创建初始化一个列表对象, 其实它相当于调用 val intList=List.apply(1,2,3),只不过 val intList=List(1,2,3)这种创建方式更简洁一点,但我们必须明确的是这种创建方式仍然避免不了 new,它后面的实现机制仍然是 new 的方式,只不过我们自己在使用的时候可以省去 new 的操作。通常我们会在类的伴生对象中定义 apply 方法,当遇到【类名(参数 1,...参数 n)】时 apply 方法会被调用。
? Apply也叫构建函数:把一堆零散的值构建成一个对象返回。
例:
object Test01 {
def main(args: Array[String]): Unit = {
//以下两种方式创建对象等效
val list01 = List(1, 2, 3)
val list02 = List.apply(1, 2, 3)
}
}
特点:
? - apply方法只能定义在object中。
? - apply方法可以重载, 还是被系统自动调用的
?
3.scala的抽象类
? 定义:抽象类是一种不能被实例化的类,抽象类中包括了若干不能完整定义的方法,这些方法由子 类去扩展定义自己的实现。
? 特点:
? ? - 如果在父类中,有某些方法无法立即实现,而需要依赖不同的子类来覆盖,重写实现自 己不同的方法实现。此时可以将父类中的这些方法不给出具体的实现,只有方法签名,这 种方法就是抽象方法。
? ? - 一个类中如果有一个抽象方法,那么类就必须用 abstract 来声明为抽象类,此时抽象 类是不可以实例化的
? ? - 在子类中覆盖抽象类的抽象方法时,不需要使用 override 关键字
例:
abstract class Annimal {
def runing()
def eat()
}
class Cat extends Annimal {
def runing(): Unit = {
println("running~")
}
def eat(): Unit = {
println("eatting~")
}
}
?
4.scala的继承
例:
//父类
class Annimal {
//被final修饰的无法被继承
final private val name = "Annimal"
def runing(): Unit = {
println("running~")
}
def eat(): Unit = {
println("eatting~")
}
}
//子类
class Cat extends Annimal {
//重写父类的方法
override def runing(): Unit = {
//调用父类原有的方法
super.runing()
}
}
注意:
? - 在 Scala 中扩展类的方式 和 Java 一样都是使用 extends 关键字
? - 继承就代表,子类可以从父类继承父类的 field 和 method;然后子类可以在自己内部放 入父类所没有,子类特有的 field 和 method;使用继承可以有效复用代码
? - 子类可以覆盖父类的 field 和 method;但是如果父类用 final 修饰,field 和 method 用 final 修饰,则该类是无法被继承的,field 和 method 是无法被覆盖的
? - 如果子类要重写一个父类中的非抽象方法,则必须使用 override 关键字
? - 使用 super 关键字,显式地指定要调用父类的方法/属性
?
5.scala的类型检查和转换
例:
object Test01 {
def main(args: Array[String]): Unit = {
val parent=new Annimal //父类
val chrild=new Cat //子类
//类型判断
println(chrild.isInstanceOf[Annimal]) //true
//类型获取
println(classOf[Cat]) //class Cat
//类型转换
val annimal: Annimal = chrild.asInstanceOf[Annimal]
}
}
//父类
class Annimal {
//被final修饰的无法被继承
final private val name = "Annimal"
def runing(): Unit = {
println("running~")
}
def eat(): Unit = {
println("eatting~")
}
}
//子类
class Cat extends Annimal {
//重写父类的方法
override def runing(): Unit = {
//调用父类原有的方法
super.runing()
}
}
?
6.scala的特质 (Trait)
(1)特质的介绍
? Scala 和 Java 语言一样,采用了很强的限制策略,避免了多继承的问题。在 Java 语言中,只允许继承一个超类,该类可以实现多个接口,但 Java 接口有其自身的局限性:接口中只能包括抽象方法,不能包含字段、具体方法。Scala 语言利用 trait 解决了该问题,在 Scala 的 trait 中,它不但可以包括抽象方法还可以包含字段和具体方法。特质在底层实现是采用的Java的抽象类。
例:
trait Annimal {
val name = "Annimal"
def runing(): Unit = {
println("running~")
}
def eat()
}
(1)特质的基本使用
特质的特点:
? - 特质里面的方法既可以实现,也可以不实现
? - 优先使用特质。一个类扩展多个特质是很方便的,但却只能扩展一个抽象类。
? - 特质不能设置带参数的构造:trait t(i: Int) {},参数 i 是非法的
? - 如果继承多个特质,使用第一个特质使用 extends,后面的使用 with
例:
trait Car {
}
trait Person{
}
class transformers extends Car with Person{
}
(2)特质作为接口使用
? 将特质中的方法全部定义成为抽象方法。类可以使用extends的方式继承特质。scala 不支持对类进行多继承,但是支持多重继承 trait,使用 with 关键字即可。类继承 trait 后,必须实现其中的抽象方法,实现时不需要使用 override 关键字。
例:
trait mysqlDAO{
val id:Int
def add(o:Any):Boolean
def update(o:Any):Int
def query(id:String):List[Any]
}
//如果有多个 trait 的话,则使用 with 关键字即可
class DaoImpl extends MySQLDAO with Serializable{
// 给父类中的抽象字段赋值。
override val id = 12
// 实现抽象方法
def add(o:Any):Boolean = true
def update(o:Any):Int = 1
def query(id:String):List[Any] = List(1,2,3)
}
(3)为实例对象混入 Trait
? 有时我们可以在创建类的对象时,指定该对象混入某个 Trait,这样,就只有这个对象混入该 Trait 的方法,而类的其他对象则没有。
例:
object Test01 {
def main(args: Array[String]): Unit = {
//会某一个对象混入特质
var HTQ_DHF =new Person() with DHF
}
}
trait transformers
trait HTQ extends transformers
trait DHF extends transformers
trait Person extends HTQ
(4)Trait 调用链
? scala 中支持让类继承多个 Trait 后,依次调用多个 Trait 中的同一个方法,只要让多个 Trait 的同一个方法中,在最后都执行 super.方法 即可。类中调用多个 Trait 中都有的这个方法时,首先会从最右边的 Trait 的方法开始执行,然后依 次往左执行,形成一个调用链条这种特性非常强大,其实就相当于设计模式中的责任链模式的一种具体实现依赖。
例:
object Test01 {
def main(args: Array[String]): Unit = {
val p=new Person_TraitChain("zhangxiaolong")
p.sayHello
}
}
trait Handler {
//父类的trait 必须有实现体,不然会报错
def handler(data:String): Unit ={
println("Handler :"+data)
}
}
trait Handler_A extends Handler{
override def handler(data:String): Unit = {
println("Handler_A :"+data)
super.handler(data)
}
}
trait Handler_B extends Handler{
override def handler(data:String): Unit = {
println("Handler_B :"+data)
super.handler(data)
}
}
trait Handler_C extends Handler{
override def handler(data:String): Unit = {
println("Handler_C :"+data)
super.handler(data)
}
}
class Person_TraitChain(val name:String) extends Handler_C with Handler_B with
Handler_A{
def sayHello={
println("Hello "+name)
handler(name)
}
}
结果会打印:
从右向左,依次调用
以上是关于Scala的面向对象的主要内容,如果未能解决你的问题,请参考以下文章