3. 类、对象、继承和trait

3.1 类

3.1.1 类的定义

Scala中,可以在类中定义类、以在函数中定义函数、可以在类中定义object;可以在函数中定义类,类成员的缺省访问级别是:public

//在Scala中,类不用声明为public
//Scala源文件中可以包含多个类,所有这些类都具有公有可见性
class Person {
//val修饰的变量是只读属性,相当于Java中final修饰的变量,只提供get()
val id = "1"
//var修饰的变量,提供get()和set()
var age: Int = 18
//类私有字段,只有本类和本类的伴生对象可以访问
private var name = "zs"
//对象私有字段只有本类能访问
private[this] val pet = "xq"
} /**(单例对象,静态对象)
* 伴生对象:与class名相同,并且在同一个文件中*/
object Person {
def main(args: Array[String]): Unit = {
val p = new Person
// p.id = "2"// p.pet
println(p.id +":"+p.age+":"+p.name)
p.name = "ls"
p.age = 20
println(p.age+":"+p.name)
}
}

3.1.2 构造器

Scala主要分主构造器和辅助构造器两种:

主构造器里面的变量会被执行,方法会被加载,调用的方法会被执行

辅助构造器(相当于重载的构造函数)不可以直接调用超类的主构造器

/**每个类都有主构造器,主构造器的参数直接放置类名后面,可以在主构造器中对字段赋值,对于主构造器中参数已赋值的在new的时候可以不再赋值
private[com.bigdata] class Study{}:只有com.bigdata或其子包下的类能访问Stu class Stu(name:String){}:构造参数name没有val、var修饰 相当于private[this] name:String ,只有本类能访问
class Stu private(name:String){}:private修饰主构造器(私有构造器),只有伴生对象能new */ class Student(val name: String, val age: Int) {
//主构造器会执行类定义中的所有语句
println("执行主构造器")
try {
println("读取文件")
throw new IOException("io exception")
} catch {
case e: NullPointerException => println("打印异常Exception : " + e)
case e: IOException => println("打印异常Exception : " + e)
} finally {
println("执行finally部分")
} private var gender = "male" //用this关键字定义辅助构造器
def this(name: String, age: Int, gender: String){
//每个辅助构造器必须以主构造器或其他的辅助构造器的调用开始
this(name, age) this.gender = gender
}
}

3.1.3 Class

Scala中类可以通过classOf[A]获取类型,Object单例/伴生只能通过.getClass获取。

classOf和getClass区别:

getClass方法得到的是Class[A]的某个子类,而classOf[A]得到是正确的 Class[A],但是去比较的话,这两个类型是equals为true的。这种细微的差别,体现在类型赋值时,因为java里的Class[T]是不支持协变的,所以无法把一个 Class[_ < : A] 赋值给一个 Class[A]。

类型检查和转换:

Scala Java
obj.isInstanceOf[C]:判断obj是否属于C类型 obj instanceof C
obj.asInstanceOf[C]:转换 (C)obj
classOf[C] C.class

3.2 对象

3.2.1 单例对象和伴生对象

1.单例对象
在Scala中没有静态方法和静态字段,但是可以使用object这个语法结构来达到同样的目的。主要作用:
1)存放工具方法和常量
2)高效共享单个不可变的实例
3)单例模式 2.伴生对象
单例对象,不需要new,用【类名.方法】调用单例对象中的方法
伴生对象
在scala的类中,与类名相同且与该类在同一个文件的对象叫伴生对象。类和伴生对象之间可以相互访问私有的方法和属性,但类的字段被private[this]修饰的只有本类能访问

3.2.2 应用程序对象

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

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

3.2.3 apply和unapply方法

通常我们会在类的伴生对象中定义apply方法,当遇到类名(参数1,...参数n)时apply方法会被调用。

apply方法有点类似于java中的构造函数,接受构造参数变成一个对象。

unapply方法就刚好相反,它是接收一个对象,从对象中提取出相应的值,主要用于模式匹配(后文阐述)中。

def main(args: Array[String]) {
//调用了Array伴生对象的apply方法
//def apply(x: Int, xs: Int*): Array[Int]
//arr1中只有一个元素5
val arr1 = Array(5)
//def apply[T: ClassTag](xs: T*): Array[T] = {}
var arr2 = Array[Int](8)
println(arr1.toBuffer)
//new了一个长度为5的array,数组里面包含5个null(没有指定泛型)
var arr2 = new Array(5)
}

3.3 继承和trait

在Scala中继承类的方式和Java一样都是使用extends关键字,继承多个类后面有with关键字。

Scala中没有接口,而是trait即特质,类似Java1.8中的接口,其中可以包含抽象方法也可以有已实现的方法。

在Scala中重写一个非抽象的方法(没有被实现)必须使用override修饰符,抽象方法可以使用也可以不使用override。

trait Flyable {
def fly(): Unit = { println("I can fly") }
}
abstract class Animal {
def run(): Int
val name: String
}
/*class Human extends Animal with Flyable
class Human extends Flyable with其他trait(特质)
*/
class Human extends Animal with Flyable {
val name = "lz"
//t1、t2、、tn打印n次ABC,t1=(1, 2, 3,4)(a->1,b->2,c->3,d->4)
val t1, t2,t3, (a, b, c,d) = {
println("ABC")
(1, 2, 3,4)
}
//scala中重写一个非抽象方法必须使用override关键字
override def fly(): Unit = { println("123") }
//重写抽象方法可以使用也可以不使用override关键字
def run(): Int = { 1 }
}
object Main {
def main(args: Array[String]): Unit = {
val h = new Human
println(h.t1+":"+h.a+":"+h.b+":"+h.c+":"+h.t2)
}
}

4. 模式匹配和样例类

4.1 模式匹配

Scala有一个十分强大的模式匹配机制,可以应用到很多场合:如替代Java中的switch语句、类型检查等。

并且Scala还提供了样例类,对模式匹配进行了优化,可以快速进行匹配。

// 1. 匹配字符串
import scala.util.Random
object Case01 extends App {
val arr = Array(1, 2, 3)
val i = arr(Random.nextInt(arr.length))
i match {
case 1 => {println(i)}
case 2 => {println(i)}
//下划线_:代表匹配其他所有类似于switch语句中default
case _ => {println(i)}
}
} // 2. 匹配类型
import scala.util.Random
object Case02 extends App {
val arr = Array("a", 1, -2.0, Case02)
val elem = arr(Random.nextInt(arr.length))
println(elem)
elem match {
case x:Int => {println("Int"+x)}
//模式匹配时可以加守卫条件,如果不符合守卫条件,走case_
case y:Double if(y>=0) => println("Double "+ y)
case Case02 => {println("Int"+Case02)}
case _ => {println("default")}
}
} // 3. 匹配数组
object Case03 extends App {
/* val arr = Array(0, 3, 5)
arr match {
case Array(1,x,y) => println(x+":"+y)
case Array(0) => println("only 0")
//表示匹配首元素是0的数组
case Array(0,_*) => println("0 ...")
case _ => println("else")
}*/
/* val lst = List(0,-1,1,2)
//head首元素,tail除首元素之外的元素 take从1开始取
println(lst.head+":"+lst.tail+":"+lst.take(1))
lst match {
//首元素0,Nil代表空列表
case 0 :: Nil => println("only 0")
//只有两个元素
case x :: y :: Nil => println(s"x:$x--y:$y")
case 0 :: x => println(s"0...$x")//head和tail
case _ => println("else")
}*/
val tup = (-1.2, "a", 5)
tup match {
//元组有几个元素,case后跟的元组也要有几个元素
case (1, x, y) => println(s"hello 123 $x , $y")
case (_, z, 5) => println(z) //前两个元素为任意值
case _ => println("else")
}
val lst1 = 9 :: (5 :: (2 :: Nil))
val lst2 = 9 :: 5 :: 2 :: List()
println(lst2+":"+lst1)//952:952
}

4.2 样例类

可用于模式匹配、封装数据(多例)。case class多例,后面跟构造函数;case object是单例的:

import scala.util.Random
case class Task(id:String)
case class HeartTime(private val time:Long)//构造case class可new可不new
case object CheckTimeOut object Main {
def main(args: Array[String]) {
val arr = Array(CheckTimeOut, HeartBeat(88888), Task("0001"))
val a = arr(Random.nextInt(arr.length)) a match {
case Task(id) => {println(s"$id")}//取id值 固定写法
case HeartTime(time) => {println(s"$time")}
case CheckTimeOutTask => {
println("check")
} //匹配其他情况
case _ => prinln("do something")
}
}
}

关注微信公众号:大数据学习与分享,获取更对技术干货

学好Spark/Kafka必须要掌握的Scala技术点(二)类、单例/伴生对象、继承和trait,模式匹配、样例类(case class)的更多相关文章

  1. 学好Spark/Kafka必须要掌握的Scala技术点(一)变量、表达式、循环、Option、方法和函数,数组、映射、元组、集合

    前言 Scala是以JVM为运行环境的面向对象的函数式编程语言,它可以直接访问Java类库并且与Java框架进行交互操作.正如之前所介绍,Spark是用Scala语言编写的,Kafka server端 ...

  2. 学好Spark/Kafka必须要掌握的Scala技术点(三)高阶函数、方法、柯里化、隐式转换

    5. 高阶函数 Scala中的高阶函数包含:作为值的函数.匿名函数.闭包.柯里化等,可以把函数作为参数传递给方法或函数. 5.1 作为值的函数 定义函数时格式: val 变量名 = (输入参数类型和个 ...

  3. Scala基础:模式匹配和样例类

    模式匹配 package com.zy.scala import scala.util.Random /** * 模式匹配 */ object CaseDemo { def main(args: Ar ...

  4. Scala单例对象、伴生对象实战详解

    1.Scala单例对象 Scala单例对象是十分重要的,没有像在Java一样,有静态类.静态成员.静态方法,但是Scala提供了object对象,这个object对象类似于Java的静态类,它的成员. ...

  5. scala学习手记15 - 独立对象和伴生对象

    上一节中的单例对象MarkerFactory 就是一个独立对象的例子.尽管它管理着Marker类,但是它并没有关联到任何类上. scala也可以创建关联到类上的对象.这样的对象同类共享同一个名字,这样 ...

  6. Scala学习十四——模式匹配和样例类

    一.本章要点 match表达式是更好的switch,不会有意外调入下一个分支 如果没有模式能够匹配,会抛出MatchError,可以用case _模式避免 模式可以包含一个随意定义的条件,称做守卫 你 ...

  7. (升级版)Spark从入门到精通(Scala编程、案例实战、高级特性、Spark内核源码剖析、Hadoop高端)

    本课程主要讲解目前大数据领域最热门.最火爆.最有前景的技术——Spark.在本课程中,会从浅入深,基于大量案例实战,深度剖析和讲解Spark,并且会包含完全从企业真实复杂业务需求中抽取出的案例实战.课 ...

  8. CDH下集成spark2.2.0与kafka(四十一):在spark+kafka流处理程序中抛出错误java.lang.NoSuchMethodError: org.apache.kafka.clients.consumer.KafkaConsumer.subscribe(Ljava/util/Collection;)V

    错误信息 19/01/15 19:36:40 WARN consumer.ConsumerConfig: The configuration max.poll.records = 1 was supp ...

  9. 大数据Spark+Kafka实时数据分析案例

    本案例利用Spark+Kafka实时分析男女生每秒购物人数,利用Spark Streaming实时处理用户购物日志,然后利用websocket将数据实时推送给浏览器,最后浏览器将接收到的数据实时展现, ...

随机推荐

  1. JS中 `=+` 是什么?

    JS中 =+ 是什么? 依然是赋值 =是赋值,+代表后面的数字为正数,同理=-代表后面的数字为负数 用处 相当于告诉编译器,即将赋值的数值类型为数字类型,不要把数字当作字符串去拼接 示例 functi ...

  2. spring boot和spring cloud版本选择

    SpringBoot版本介绍 官网链接:https://spring.io/projects/spring-boot#learn Spring Boot的版本以数字表示.例如:Spring Boot ...

  3. Go语言实现excel导入无限级菜单结构

    目录 需求 实现 测试 简单例子 复杂例子 需求 最近有一个需求,要实现一个无限级结构的树型菜单,差不多长下面这个样子 我们知道无限级实现思路都是用一个parent_id将各种层级串联起来,顶级的pa ...

  4. 轻松将CAD文件转为加密的PDF文件

    对于从事设计相关工作的朋友来说,CAD肯定再熟悉不过了.一些有特殊要求的CAD文件,需要将其转换成为PDF文件以方便保存.传输.打印,同时还得保证设计图稿的安全性,所以将CAD文件直接转为加密的PDF ...

  5. MySQL优化篇(未完待续)

    一.优化SQL语句的一般步骤 1.通过 show status命令了解各种sql的执行频率 mysql客户端连接成功后,通过show[session|global] status命令,可以查看服务器的 ...

  6. 【PUPPETEER】初探之获取元素文本值(三)

    一.知识点 page.$eval(selector, pageFunction[, ...args]) page.$$eval(selector, pageFunction[, ...args]) i ...

  7. bash反弹shell检测

    1.进程 file descriptor 异常检测 检测 file descriptor 是否指向一个socket 以重定向+/dev/tcp Bash反弹Shell攻击方式为例,这类反弹shell的 ...

  8. Goland 2020.2.x 激活码永久破解教程 (最新Goland激活码!2020.11.26亲测可用!)

    在2020.11.26 Goland的用户们又迎来了一次更新,这就导致很多软件打开时候就提示Goland激活码已经失效,码小辫第一时间给各位分享了关于最新Goland激活破解教程! goland已经更 ...

  9. 4 种高可用 RocketMQ 集群搭建方案!

    背景 笔者所在的业务线,最初化分为三个服务,由于业务初期业务复杂度相对简单,三个业务服务都能很好的独立完成业务功能. 随着产品迭代,业务功能越来越多后慢慢也要面对高并发.业务解耦.分布式事务等问题,所 ...

  10. apply 、call 以及 bind 的使用和区别

    一.被apply和call调用的函数中没有传递参数 (一)不传参数 结果: (二)传递 null 结果: 总结: 1.当使用 apply和 call去调用函数并且没有传递参数时,前提这个函数中也没有传 ...