scala类与对象、特征、模式匹配

一、类和对象

  • 类是对象的抽象,而对象是类的具体实例。类是抽象的,不占用内存,而对象是具体的,占用存储空间。
  • 类是用于创建对象的蓝图,它是一个定义包括在特定类型的对象中的方法和变量的软件模板。
  • Scala中的类不声明为public,一个Scala源文件中可以有多个类。
  • Scala 的类定义可以有参数,称为类参数类参数在整个类中都可以访问。 

scala面向对象基本上与Java SE中OOP(面向对象编程)类似。

  • 在Scala中声明private变量,Scala编译器会自动生成get,set方法
  • 在Scala中变量需要初始化
  • 在Scala中没有静态修饰符static,在object下的成员全部都是静态的
  • 如果在类中声明了与该类同名的object则该object是该类的”伴生对象”
  • 可以理解为Scala把类中的static集中放到了object对象中,伴生对象和类文件必须是同一个源文件,可以用伴生对象做一些初始化操作.
  • 在Java中可以通过interface实现多继承,在Scala中可以通过特征(trait)实现多重继承,但是与Java不同的是,它可以定义自己的属性和实现方法体
  • object不能提供构造器参数,也就是说object必须是无参的

Scala中object与class的区别

在Scala中,类可以和对象同名,该对象称为该类的伴生对象,类和伴生对象可以相互访问他们的私有属性,但是它们必须在同一个源文件中

类只会被编译,不能直接执行,类的声明和主构造器在一起被声明,在一个类中,主构造器只有一个.

类和它的伴生对象可以相互访问其私有成员

class和object的一个差别是,单例对象不带参数,而类可以.因为你不能用new关键字实例化一个单例对象,你没有机会传递给它参数

1、类&属性&方法的定义

eg:

class People {
  //定义属性
  var name:String=""
  val age:Int=10
  
  //定义方法
  def  eat():String={
    name+"eat pipea"
  }
  
  def watchFootball(teamName:String): Unit ={
    println(name+"is watching match of "+teamName)
  }
}
object SimpleObjectDemo {
  def main(args: Array[String]): Unit = {
    val people = new People()      //创建对象
    people.name="Messi"       //为namme赋值
    println("name is :"+people.name)
    println("name is :"+people.name+"age is :"+people.age)

    //函数调用
    println("invoke eat method:"+people.eat())

    //
    println("incoke watchFootball method:"+people.watchFootball("Barcelona"))
  }
}

2、构造方法

eg:

class ConstrutorExtendsDemo {

}
定义类时定义的方法参数是默认构造方法
class Person (val name:String,val age:Int){
  println("Person constructor enter~~~~~~~~~~~~~~~~")
  val school="kgc"
  println("Person constructor leave~~~~~~~~~~~~~~~")
}
class ConstrutorExtendsDemo extends App{
  //调用主构造器
  var person=new Person("zhangsan",21)
  println("name is:"+person.name+",age is :"+ person.age+",school is :"+person.school)
}

3、继承

Scala继承一个基类跟Java很相似, 但我们需要注意以下几点:

  • 重写一个非抽象方法必须使用override修饰符。
  • 只有主构造函数才可以往基类的构造函数里写参数。
  • 在子类中重写超类的抽象方法时,不需要使用override关键字。
class Student(name:String,age:Int,var major:String) extends Person(name,age){
  println("Student constructor enter~~~~~~~~~")
  println("Student constructor leave~~~~~~~~~~~~~~~")
}
class ConstrutorExtendsDemo extends App{
 //初始化子类对象
  var student = new Student("wangwu",15,"Math")
  println("name is :"+ student.name + "age is :"+ student.age + "major is :"+ student.major + "school is :"+ student.school)
  println(student)
}

注意:

  • Scala 使用 extends 关键字来继承一个类。父类(基类),子类。
  • 继承会继承父类的所有属性和方法,Scala 只允许继承一个父类。
  • 子类构造方法触发之前要先触发其父类的构造方法
  • 父类中已有的字段无需使用val/var修饰,只有新增的字段才需要val/var修饰

4、抽象类

scala中抽象类的特点:

1)  类的一个或多个方法没有完整的实现(只有定义,没有实现)

2)声明抽象方法不需要加abstract关键字,只需不写方法体

3)子类重写父类的抽象方法时不需加override

4)子类重写父类的抽象属性时不需加override

5)父类可以声明抽象字段(没有初始值的字段)

class AbstractDemo {

}
abstract class Person2 {
  //属性和方法无需添加abstract关键字
  def  speak
  
  val name:String
  var age:Int
}
class Student2 extends Person2{
def speak(): Unit ={
  //返回值为Unit
  println("speak~~~~~~~~~~")
}
  val name="zhangsan"
  var  age=100
}
class AbstractDemo extends App{
  val s = new Student2
  s.speak()
  println("name is:"+s.name+",age is "+s.age)
}

5、单例对象

在 Scala 中没有 static 关键字,但是它也为我们提供了单例模式的实现方法,那就是使用关键字 object。

  • scala 的object 中所有成员变量和方法默认都是 static 的,所以可以直接访问main方法

Scala 中使用单例模式时,除了定义的类之外,还要定义一个与类同名的 object 对象,区别是:object对象不能带参数。

  • 当单例对象与类同名时,该单例对象被称作是该类的伴生对象:companion object
  • 类和其伴生对象必须在同一个源文件里,该类被称为是这个单例对象的伴生类:companion class
  • 类和其伴生对象可以互相访问其私有成员。

eg:单例对象实例

class Point(val xc: Int, val yc: Int) {
   var x: Int = xc
   var y: Int = yc
   def move(dx: Int, dy: Int) {
      x = x + dx
      y = y + dy
   }
}

object Test {
   def main(args: Array[String]) {
      val point = new Point(10, 20)
      printPoint

      def printPoint{
         println ("x 的坐标点 : " + point.x);
         println ("y 的坐标点 : " + point.y);
      }
   }
}

eg:伴生对象实例:

//私有构造方法
class Marker private(val color:String){
  println("创建"+this)
  override def toString(): String = "颜色标记"+color
}

//伴生对象,与类共享名,可以访问类的私有属性和方法
object Marker {
  //定义了一个map类型的变量--》markers
  private val markers:Map[String,Marker] = Map(
    "red" -> new Marker("red"),
    "blue" -> new Marker("blue"),
    "green" -> new Marker("green")
  )

  def apply(color: String)={
    if (markers.contains(color))  markers(color) else null
  }

  def getMarker(color: String)={
    if (markers.contains(color)) markers(color) else null
  }

  def main(args: Array[String]){
    println(Marker("red"))
    //单例函数调用
    println(Marker.getMarker("blue"))

  }
}

二、特征 Trait

      scala Trait(特征)相当于java中的接口,实际比接口功能强大。

      区别于接口:scala Trait还可以定义属性和方法的实现。

      一般情况下,scala类只能继承单一父类,但是scala  Trait(特征)可实现多重继承

      使用关键字trait定义特征

      子类继承特征可以实现未被实现的方法。所以其实 Scala Trait(特征)更像 Java 的抽象类。

      eg:

//isEqual方法没有定义方法的实现,isNotEqual定义了方法的实现
trait Equal {
  def isEqual(x: Any): Boolean
  def isNotEqual(x: Any): Boolean = !isEqual(x)
}
 子类继承特征可以实现未被实现的方法class Point(xc:Int,yc:Int) extends Equal{
  var x:Int = xc
  var y:Int = yc
  
  def  isEqual(obj:Any)=
//类型判断
    obj.isInstanceOf[Point]&&
//强制类型转换
    obj.asInstanceOf[Point].x == x
}
object Test {
  def main(args: Array[String]) {
    val p1 = new Point(2,3)
    val p2 = new Point(2,4)
    val p3 = new Point(3,3)

    println(p1.isNotEqual(p2))        //true
    println(p1.isNotEqual(p3))     //true
    println(p1.isNotEqual(2))     //true
  }
}

特征构造顺序

特征也可以有构造器,由字段的初始化和其他特征体中的语句构成。这些语句在任何混入该特征的对象在构造时都会被执行。

构造器的执行顺序:

  • 调用超类的构造器;
  • 特征构造器在超类构造器之后、类构造器之前执行;
  • 特征由左到右被构造;
  • 每个特征当中,父特征先被构造;
  • 如果多个特征共有一个父特征,父特征不会被重复构造
  • 所有特征被构造完毕,子类被构造。

构造器的顺序是类的线性化的反向。线性化是描述某个类型的所有超类型的一种技术规格。

三、模式匹配

Scala 提供了强大的模式匹配机制,应用也非常广泛。

一个模式匹配包含了一系列备选项,每个都开始于关键字 case。每个备选项都包含了一个模式一到多个表达式

箭头符号 => 隔开了模式和表达式。

eg:

match 对应 Java 里的 switch,但是写在选择器表达式之后。即: 选择器 match {备选项}。

match 表达式通过以代码编写的先后次序尝试每个模式来完成计算,只要发现有一个匹配的case,剩下的case不会继续匹配。

 eg:不同数据类型的模式匹配

 实例中第一个 case 对应整型数值 1,第二个 case 对应字符串值 two,第三个 case 对应类型模式,用于判断传入的值是否为整型,相比使用isInstanceOf来判断类型,使用模式匹配更好。第四个 case 表示默认的全匹配备选项,即没有找到其他匹配时的匹配项,类似 switch 中的 default。

1、样例类case class

使用了case关键字定义的类---->样例类(case classes),样例类是特殊的类,经过优化以用于模式匹配。

eg:

在声明样例类时,下面的过程自动发生了:

  • 构造器的每个参数都成为val,除非显式被声明为var,但是并不推荐这么做;
  • 在伴生对象中提供了apply方法,所以可以不使用new关键字就可构建对象;
  • 提供unapply方法使模式匹配可以工作;
  • 生成toString、equals、hashCode和copy方法,除非显示给出这些方法的定义。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值