Scala:(五) 类、对象、继承、模式匹配和样例类

一般类名首字母大写 ,方法首字母小写,类和方法命名建议符合驼峰命名法。

  1. scala中的class类默认可以传参数,默认的传参数就是默认的构造函数。重写构造函数的时候,必须要调用默认的构造函数。
  2. 在Scala中,类并不用声明为public。Scala源文件中可以包含多个类,所有这些类都具有公有可见性。
  3. class 类属性自带getter ,setter方法。用val修饰的变量是只读属性,有getter但没有setter(相当与Java中用final修饰的变量);用var修饰的变量既有getter又有setter
  4. 类私有字段,只能在类的内部使用;

定义一个类

class Person{
  val name = "zhangsan"
  val age = 18
  def sayName() = {
    "my name is "+ name
  }
}

构造器

对象

定义一个对象
在Scala中没有静态方法和静态字段,但是可以使用object这个语法结构来达到同样的目的。使用object时,不用new,使用class时要new ,并且new的时候,class中除了方法不执行,其他都执行。

1.存放工具方法和常量
2.高效共享单个不可变的实例
3.单例模式

object Lesson_Class {
   def main(args: Array[String]): Unit = {
    val person = new Person()
    println(person.age);
    println(person.sayName())
  }
}

伴生对象

如果在同一个文件中,object对象和class类的名称相同,则这个对象就是这个类的伴生对象(在Scala的类中,与类名相同的对象叫做伴生对象),这个类就是这个对象的伴生类。可以互相访问私有变量。


// 类
  class Car{
  // 私有属性
    private var name = "laosiji"

    def printName(): Unit ={
      //在Dog类中可以访问伴生对象Dog的私有属性
      println(Car.myCar + name )
    }
  }

// 与类同名的,伴生对象
  object Car {
    //伴生对象中的私有属性
    private val myCar = "老司机,来开车啦: "

    def main(args: Array[String]) {
      val car = new Car
      //可以访问私有的字段name
      car.name = "老老司机"
      // 调用其方法
      car.printName()
    }
  }

应用程序对象

Scala程序都必须从一个对象的main方法开始,可以通过扩展App特质,不写main方法

object AppObjectDemo extends App{
  //不用写main方法
  println("I love you Scala")
}

继承

在Scala中扩展类的方式和Java一样都是使用extends关键字,在Scala中重写一个非抽象的方法必须使用override修饰符
类型检查和转换

Scala Java
obj.isInstanceOf[C] obj.instanceof( C)
obj.asInstanceOf[C] (C)obj
classOf[C] C.class

代码直接看下面trait中菜鸟教程的代码即可

Trait

Scala Trait(特征) 相当于 Java 的接口,实际上它比接口还功能强大。与接口不同的是,它还可以定义属性和方法的实现
这里的trait字面意思是特质或者特征,这个词翻译成特征比较合适。它的意义和java,c#中接口很类似。但是trait支持部分实现,也就是说可以在scala的trait中可以实现部分方法。
一般情况下Scala的类可以继承多个Trait,从结果来看就是实现了多重继承。Trait(特征) 定义的方式与类类似,但它使用的关键字是 trait。
继承的多个trait中如果有同名的方法和属性,必须要在类中使用“override”重新定义。
trait中不可以传参数

trait Read {
  val readType = "Read"
  val gender = "m"
  def read(name:String){
	println(name+" is reading")
  }
}

trait Listen {
  val listenType = "Listen"
  val gender = "m"
  def listen(name:String){
	println(name + " is listenning")
  }
}

class Person() extends Read with Listen{
  override val gender = "f"
}

object test {
  def main(args: Array[String]): Unit = {
    val person = new Person()
    person.read("zhangsan")
    person.listen("lisi")
    println(person.listenType)
    println(person.readType)
    println(person.gender)
    
  }
}

一下引用菜鸟教程的部分内容,原文摘录:

/* 文件名:Test.scala
 * author:菜鸟教程
 * url:www.runoob.com
 */
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))
      println(p1.isNotEqual(p3))
      println(p1.isNotEqual(2))
   }
}

执行结果为:

false
true
true

模式匹配

Scala有一个十分强大的模式匹配机制,可以应用到很多场合:如switch语句、类型检查等。并且Scala还提供了样例类,对模式匹配进行了优化,可以快速进行匹配
一个模式匹配包含了一系列备选项,每个都开始于关键字 case。
每个备选项都包含了一个模式及一到多个表达式。箭头符号 => 隔开了模式和表达式。

object BasicTest {
  def main(args: Array[String]): Unit = {
    val tuple = Tuple6(1, 2, 3f, 4, "abc", 55d)
    // 可以使用 Tuple.productIterator() 方法来迭代输出元组的所有元素
    val tupleIterator = tuple.productIterator
    while (tupleIterator.hasNext) {
      matchTest(tupleIterator.next())
    }
  }
  /**
   * 注意点:
   * 1.模式匹配不仅可以匹配值,还可以匹配类型
   * 2.模式匹配中,如果匹配到对应的类型或值,就不再继续往下匹配
   * 3.模式匹配中,都匹配不上时,会匹配到 case _ ,相当于default
   */
  def matchTest(x: Any) = {
    x match {
      case x: Int => println("type " + x +" is Int" )
      case 1 => println("result " + x +" is 1")
      case 2 => println("result " + x +" is 2")
      case 3 => println("result " + x +" is 3")
      case 4 => println("result " + x +" is 4")
      case x: String => println("type " + x +"  is String")
      case _ => println(x + " no match")
    }
  }
}

样例类

样例类可简单理解为就是一个Java中的实体类,只不过其默认实现了无参和全参的构造器(当然如果参数有默认值的话,使用的地方有默认值的参数可不传)。
其使用时可以不用new关键字(实现了apply方法);其内val定义的变量默认实现getter方法;var定义的变量默认实现get和set方法;还默认实现了tostring,eques等方法
case class是多例的,case object是单例的
借用小伙伴的一段代码来表示其使用:
定义了一个样例类

case class DPISrcDataStatistic( prov_id : String , prov_id1 : String = "j") {
  //统计字段记录数
  var total_count   = 1L
  //统计字段异常或空值记录数
  var device_number_exce   = 0L
  var lac_exce             = 0L

使用该样例类

val tmp = DPISrcDataStatistic(provId)
    lineArray.indices.foreach(x => {
      x match {
        case 0 =>  if(lineArray(x).isEmpty) tmp.device_number_exce   = 1
        case 1 =>  if(lineArray(x).isEmpty) tmp.lac_exce             = 1
        case 2 =>  if(lineArray(x).isEmpty) tmp.ci_exce              = 1
        case _  => log.warn(s"省份: ${provId} 原数据: ${lineArray.mkString("|")}   问题列: ${lineArray(x)}")
      }
    })
posted @ 2020-07-29 17:36  手心里的宇宙  阅读(469)  评论(0编辑  收藏  举报