yunfenglee 2020-02-12
定义:实现一个抽象类 或者 Trait 时 可以通过内部类的方式完成
abstract class Cmx {
def func: Unit
}
def main(args: Array[String]): Unit = {
var cmx = new Cmx {
override def func: Unit = {
println("我是内部类")
}
}
cmx.func
//我是内部类
}定义:类似于其它语言的接口
格式:trait 名称{
//抽象成员方法或属性
//普通成员方法或属性
}
注意:Trait中的抽象成员 必须全部实现 ,不然程序报错,如果实现不完整 只能称这个类为抽象类 需要加上abstract字段
trait cmx {
//抽象属性和普通属性
var name: String
var age = 10
//抽象方法和普通方法
def func(): Unit
def func1(): Unit = {
println("我是特质的普通方法")
}
}
class cmx01 extends cmx {
override var name = "cmx01"
override def func(): Unit = {
println("必须重写")
}
}
def main(args: Array[String]): Unit = {
var a = new cmx01
a.func()
println(a.name)
//必须重写
//cmx01
}Trait与abstract的区别
1. abstract是单根继承体系,只能继承一个父类
Trait是多继承体系,可以被继承多个父类,使用关键字with
2. 在实战中,抽象类 表达的是 抽象的概念 名词
trait 表达的是 抽象的行为 动词
区别一
class Person
trait Cmx
trait Cmx01
class User extends Person with Cmx with Cmx01 {
print("---------")
}
def main(args: Array[String]): Unit = {
var a = new User
//主构造器的返回结果
//---------
}区别二
//打印日志是实际的动作,是个动词
trait Logger {
def log(msg: String)
}
class ConsoleLogger extends Logger {
override def log(msg: String): Unit = println(s"---控制台打印日志${msg}---")
}
class DBLogger extends Logger {
override def log(msg: String): Unit = println("----数据库存储日志----")
}
def main(args: Array[String]): Unit = {
var logger = new ConsoleLogger
logger.log("ok")
//---控制台打印日志ok---
}object 继承trait
trait cmx {
def func(): Unit
}
object A extends cmx {
override def func(): Unit = {
println("单例对象继承特质类")
}
}
def main(args: Array[String]): Unit = {
A.func()
//单例对象继承特质类
}trait 可以和父类共存,但是注意父类一定要在前面,trait在后面,因为之后trait才能用with关键字
以下案例,将演示以上的案例,同时演示继承的构造顺序
class Person {
println("执行Person构造器")
}
trait Cmx {
println("执行Cmx构造器")
}
trait Cmx01 extends Cmx {
println("执行cmx01构造器")
}
trait Cmx02 extends Cmx {
println("执行cmx02构造器")
}
class User extends Person with Cmx01 with Cmx02 {
print("执行User构造器")
}
def main(args: Array[String]): Unit = {
var a = new User
//执行Person构造器
//执行Cmx构造器
//执行cmx01构造器
//执行cmx02构造器
//执行User构造器
}对象混入trait
class Cmx() {
def func(): Unit = {
println("我是一个普通的类")
}
}
trait Cmx01 {
def func1(): Unit = {
println("我是一个特质的类")
}
}
def main(args: Array[String]): Unit = {
var a = new Cmx with Cmx01
a.func()
a.func1()
//我是一个普通的类
//我是一个特质的类
}trait 也可以继承class
class Cmx() {
def func(): Unit = {
println("我是一个普通的类")
}
}
trait Cmx01 extends Cmx {
def func1(): Unit
}
class Test extends Cmx01 {
override def func1(): Unit = {
println("我是一个特质的实现")
}
}
def main(args: Array[String]): Unit = {
var a = new Test
a.func()
a.func1()
//我是一个普通的类
//我是一个特质的实现
}定义:一种特殊的类,用来快速定义一个保存数据的类,类似与Java的实体,在后续spark,flink中及其重要
回顾已经学过的类:类,单例对象,半生对象,抽象类,Trait类,样例类
语法: case class 类名(属性名:属性类型...){...} ##这种写法,属性值的修饰符 是 val ,属性值不可变
case class 类名(var 属性名:属性类型...){...} ##这种写法 的属性值可以改变
注意:样例类使用来存储数据用的,所以没有方法
case class Cmx(var name: String) {
}
def main(args: Array[String]): Unit = {
var a = Cmx("cmx")
println(a.name)
//cmx
a.name = "cmx01"
println(a.name)
//cmx01
}样例类的隐含方法
1.apply:快速创建对象,省去new关键字的书写
2.toString:将对象的内容,自动转换成字符串显示;而普通的类默认输出的是这个对象的地址(包.单利对象$类名@16进制hash码)
//普通类,改写默认方法
class Cmx(name: String) {
override def toString: String = {
return s"name= ${name}"
}
}
//普通类,为改写默认方法
class Cmx01(name: String) {}
def main(args: Array[String]): Unit = {
var a = new Cmx("cmx")
var b = new Cmx01("cmx01")
println(a.toString)
//name= cmx
println(b.toString)
// #@符号后的是十六进制的哈希码
println(b.hashCode())
//13648335 #这个方法返回的是十进制的哈希码
println(Integer.toHexString(b.hashCode()))
//d041cf #结果和前面的一样
}3.equals方法:可以进行样例类,内容的比较
判断引用的方法eq()
判断内容的方法 equals(),==
case class Cmx(name: String) {}
def main(args: Array[String]): Unit = {
var a = Cmx("cmx")
var b = Cmx("cmx")
println(a.equals(b))
//true
println(a.eq(b))
//false
}4.hascode方法:获取对象的哈希码,用于进行哈希操作,进行去重操作
注意:每个对象都有哈希码,但是哈希码不能代表对象的唯一标识
同一个对象的哈希码一定是相同的,不同对象的哈希码有可能是相同的
case class Cmx(name: String) {
}
def main(args: Array[String]): Unit = {
var a = Cmx("cmx")
var b = Cmx("cmx")
println(a.hashCode())
println(b.hashCode())
println(a.eq(b))
//结果验证样例类的哈希码和内容保持一致,说明样例类修改了原来类的hashCode()
//-351660709
//-351660709
//false
}5.copy方法:快速实现一个相同的对象(指的是数据内容相同)
case class Person(name: String, age: Int)
def main(args: Array[String]): Unit = {
var a = Person("cmx", 11)
var b = a.copy("cmx01")
print(b.toString)
//Person(cmx01,11)
}语法: case object 对象名字
定义枚举 : 一个类型 有有限的对象 (Sex Season ),在scala中通过 trait 和 样例对象 可以配合定义枚举类型
//性别 特质类
trait Sex
//样例对象 继承性别类
case object Male extends Sex
case object Female extends Sex
//样例类 参数性别的类型是Sex
case class Person(name: String, sex: Sex)
def main(args: Array[String]): Unit = {
var p = Person("suns", Male)
var p1 = Person("liwj", Female)
}1.基本匹配
2.类型匹配
3.if条件判断匹配 守卫
4.样例类匹配
5.集合匹配
//基本匹配
var a = StdIn.readLine()
a match {
case "cmx" => println("cmx")
case "cmx01" => println("cmx01")
case _ => println("都不是")
}
//cmx//类型匹配
var a: Any = 10
//模式匹配是可以有返回值的
//可以用一个参数代表a的值, 借以使用
var b = a match {
case x: String => s"String${x}"
case x: Int => s"Int${x.toString}"
}
//println(b)
//Int10//if 条件判断 守卫
var a = 7
a match {
case _ if a >= 0 && a <= 3 => println("0---3")
case _ if a >= 4 && a <= 8 => println("4---8")
case _ => println("为匹配")
}
//4---8//样例类匹配
case class Cmx(name: String)
case class Cmx01(age: Int)
var m: Any = Cmx("cmx")
var p: Any = Cmx01(20)
p match {
case Cmx(name) => println("cmx类")
case Cmx01(age) => println("cmx01类")
}
//cmx01类//集合匹配
//三种形式
/*
List(1,_*):以1开头的列表
List(1):只有1一个元素的列表
List(1,x,y):以1 开头只有三个元素的列表
*/
var a = List(1, 2, 3, 4)
a match {
case List(1, _*) => println("该列表是1以开头的")
case List(1, x, y, z) => println("该列表共有4个元素")
case List(1) => println("该列表只有1 一个元素")
}
//该列表是1以开头的