面向对象
class和object的区别
- class就是普通的类,调用其他方法或者属性需要获得类的实例
- object是单例对象 不用new可以直接调用方法属性 效果上看相当于java中static修饰的
- 因为main方法是程序的入口 需要的一个调用,所以通常把main方法写在object中
val和var的区别
main方法
def main(args : Array[String]):Unit = {}
还可以通过继承App的方式间接使用main方法,不建议
伴生类
如果有一个属性只能自己访问,不想让伴生对象访问。可以通过以下方式private[This]限制伴生对象访问
extends
如果一个类不需要new,有两种情况:1.它本身就是object类;2.它使用了apply方法。
父类中使用val定义的属性,子类可以使用override关键字对其值进行修改
但是如果使用private和final关键字修饰,子类继承不了。
子类中调用父类中的方法使用super关键字
检测类的类型是否匹配,isInstanceOf不能精准判断,精准判断使用getClass == classOf。asInstanceOf并不能实现类的转化。
构造器
类中的辅助构造器第一行只能调用自己的主构造器或者其他已经存在的辅助构造器,子类只能通过子类中的主构造器调用父类的构造器。
抽象类
继承抽象类的子类要么实现父类中的方法,要么继续抽象
trait
trait中可以定义没有实现的方法,或者没有初始值的属性,这时相当于java中的接口,但是trait中的方法可以具体实现,可以被继承。trait的继承依然使用extends,多继承使用关键字with
scala中可以在创建类的实例的时候 通过with关键字混入具体的trait,但是前提:trait中的方法已经实现,否则继承后需要实现
trait的调用链
一个类可以继承多个trait每个trait可以通过同一个方法形成首尾相连的链 通过super调用父类的规则:从右往左依次调用 最后调用父类的
trait HandlerTrait {
def handle(data: String) = {println("last one")}
}
trait DataValidHandlerTrait extends HandlerTrait {
override def handle(data: String) = {
println("check data: " + data)
super.handle(data)
}
}
trait SignatureValidHandlerTrait extends HandlerTrait {
override def handle(data: String) = {
println("check signature: " + data)
super.handle(data)
}
}
class PersonForRespLine(val name: String) extends SignatureValidHandlerTrait with DataValidHandlerTrait {
def sayHello = {
println("Hello, " + this.name)
this.handle(this.name)
}
}
object PersonForRespLine{
def main(args: Array[String]) {
val p=new PersonForRespLine("tom")
p.sayHello
//执行结果:
// Hello, tom
// check data: tom
// check signature: tom
// last one
}
}
trait的构造机制:父类的构造函数先执行,class类必须放在最左边,多个trait从左往右依次执行,如果trait有父类,先执行父类构造后执行trait。
class Person_One {
println("Person's constructor!")
}
trait Logger_One {
println("Logger's constructor!")
}
trait MyLogger_One extends Logger_One {
println("MyLogger's constructor!")
}
trait TimeLogger_One extends Logger_One {
println("TimeLogger's contructor!")
}
class Student_One extends Person_One with MyLogger_One with TimeLogger_One {
println("Student's constructor!")
}
object exe_one {
def main(args: Array[String]): Unit = {
val student = new Student_One
//执行结果为:
// Person's constructor!
// Logger's constructor!
// MyLogger's constructor!
// TimeLogger's contructor!
// Student's constructor!
}
}
模式匹配和样例类
模式匹配
可以匹配值,类型,数组,集合
表达式:
match {
case
case
...
_
}
s表达式:s" "
s"x是多少:$x"
样例类
被case修饰的类称为样例类 系统会自动创建伴生对象和apply方法,可以直接用,不用new
Option类型
option类型用来表示可能存在或者可能不存在的值(option的子类有Some和None)Some包装了某个值,None表示没有值。
偏函数
没有match,但是有case的形式
A表示输入的参数类型,B表示返回结果类型
val function:PartialFunction[A,B] = {
case "good" => 2
case "bad" => 1
case _ => -1
}
协变(+)、逆变(-)、非变
- C[+T]:如果A是B的子类,那么C[A]是C[B]的子类。
- C[-T]:如果A是B的子类,那么C[B]是C[A]的子类。
- C[T]:无论A和B是什么关系,C[B]和C[A]没有从属关系。
出现错误的原因,类型不匹配,前边RDD是(int,string,int)后边是person类型。导致错误。
解决:
将RDD中的类型变为person即可
class Super
class Sub extends Super
//协变
class Temp1[+A](title: String)
//逆变
class Temp2[-A](title: String)
//非变
class Temp3[A](title: String)
object Covariance_demo{
def main(args: Array[String]) {
//支持协变 Temp1[Sub]还是Temp1[Super]的子类
val t1: Temp1[Super] = new Temp1[Sub]("hello scala!!!")
//支持逆变 Temp1[Super]是Temp1[Sub]的子类
val t2: Temp2[Sub] = new Temp2[Super]("hello scala!!!")
//支持非变 Temp3[Super]与Temp3[Sub]没有从属关系,如下代码会报错
//val t3: Temp3[Sub] = new Temp3[Super]("hello scala!!!")
//val t4: Temp3[Super] = new Temp3[Sub]("hello scala!!!")
println(t1.toString)
println(t2.toString)
}
}
scala中的上下界
- U >: T 这是类型下界的定义,也就是U必须是类型T的父类(或本身,自己也可以认为是自己的父类)。
- S <: T 这是类型上界的定义,也就是S必须是类型T的子类(或本身,自己也可以认为是自己的子类)。