微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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,3),只不过 val intList=List(1,3)这种创建方式更简洁一点,但我们必须明确的是这种创建方式仍然避免不了 new,它后面的实现机制仍然是 new 的方式,只不过我们自己在使用的时候可以省去 new 的操作。通常我们会在类的伴生对象中定义 apply 方法,当遇到【类名(参数 1,...参数 n)】时 apply 方法会被调用
? Apply也叫构建函数:把一堆零散的值构建成一个对象返回
例:

object Test01 {
  def main(args: Array[String]): Unit = {
    //以下两种方式创建对象等效
    val list01 = List(1,3)
    val list02 = List.apply(1,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的类型检查和转换

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,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的面向对象

从右向左,依次调用

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐