scala_2
一、scala类 1、 在java中程序的入口是main方法-》定义在class中 在scala中程序的入口是main方法-》定义在object对象中 案例一: class People { //定义属性 var name:String="" val age:Int=20 //定义方法 def sleep():String={ name+" is sleeping" } def wachTV(TVName:String)={ println(name +" is waching " + TVName) } } object Demo1{ def main(args: Array[String]) { val p=new People() p.name="Lili" println(p.sleep()) p.wachTV("DongFang") } } ------------------------------------- 2、scala中的object相关概念 --scala中的程序入口是main方法,main方法需要定义在object对象中 --object对象相当于其class类的单个实例,里面一般放一些静态的方法或属性 --如果一个class类,还有一个与class同名的object对象: 这个object就称为该class类的伴生对象 这个class类就称为该object对象的伴生类 @@@@前提是他们必须定义在同一个.scala文件中@@@@ 伴生对象和伴生类最大的特点是可以互相访问对方的私有属性 在调用object对象时,会执行在object中所有的代码 class People { //定义属性 var name: String = "" val age: Int = 20 private val sex: String = "female" //定义方法 def sleep(): String = { name + " is sleeping" } def wachTV(TVName: String) = { println(name + " is waching " + TVName + " with " + People.eyeNm + " eyes ") //可以调用其伴生对象的私有属性 } } object People extends App { private val eyeNm: Int = 2 val p = new People() p.name = "Lili" println(p.sleep()) p.wachTV("DongFang") println("sex:" + p.sex) //可以调用其class类的私有属性 } 3、apply方法 通常我们在伴生对象中定义apply方法,在方法中实现构造伴生类实例的功能 apply方法的方法名称必须使用apply apply方法的参数接收与class类主构造方法相同的参数,并返回该类的实例 (体现了scala语言的简洁性) object People extends App { def apply() = { println("****apply function has been invoked!!*******") new People() } private val eyeNm: Int = 2 val p =People() p.name = "Lili" println(p.sleep()) p.wachTV("DongFang") println("sex:" + p.sex) } ****apply function has been invoked!!******* Lili is sleeping Lili is waching DongFang with 2 eyes sex:female class People(var school:String) { //定义属性 var name: String = "" val age: Int = 20 private val sex: String = "female" //定义方法 def sleep(): String = { name + " is sleeping" } def wachTV(TVName: String) = { println(name + " is waching " + TVName + " with " + People.eyeNm + " eyes ") } } object People extends App { def apply(school:String) = { //apply方法的参数接收与class类主构造方法相同的参数 println("****apply function has been invoked!!*******") new People(school) } private val eyeNm: Int = 2 val p =People("beifeng") p.name = "Lili" println(p.sleep()) p.wachTV("DongFang") println("sex:" + p.sex) } ---------------------------------------- 4、构造方法 在scala中对应class类,分为主构造方法和附属构造方法 主构造方法直接跟在类名的后面,主构造方法中的参数最后会被编译成字段属性 主构造方法一般使用val或var修饰: val 定义的属性是不可变变量 var 定义的属性是可变变量 如果在主构造方法中定义变量时没有使用val或var,那么这个属性相当于该class类的private私有属性,并且只能在class内部使用,伴生对象中也不能访问 Demo1: class Person(val name: String, val age: Int) { val school: String = "beifeng" } object Demo2 extends App { val person = new Person("tom", 21) println("name:" + person.name + ",age:" + person.age + ",school:" + person.school) } Demo2: class Person( name: String, val age: Int) { val school: String = "beifeng" def printName()={ println(name) } } object Person extends App { val person = new Person("tom", 21) println("name:" + person.name + ",age:" + person.age + ",school:" + person.school) //因为name没有使用val或var修饰,所以在该伴生对象中也不能被访问到 } 附属构造方法 附属构造方法中一定要调用主构造方法 附属构造方法的名称this 每个附属构造方法的第一行需要调用已经存在的主构造器或者其他附属构造器 Demo3: class Person(var name: String, val age: Int) { val school: String = "beifeng" var sex: String = "" def this(name: String, age: Int, sex: String) = { this(name, age) this.sex = sex } def printName() = { println(name) } } object Person extends App { val person = new Person("tom", 21) println("name:" + person.name + ",age:" + person.age + ",school:" + person.school) var person1=new Person("mary",22,"male") println("name:" + person1.name + ",age:" + person1.age + ",school:" + person1.school+",sex:"+person1.sex) } 5、异常处理 对异常的捕获使用到了scala中的模式匹配语法 object Demo3 extends App { try { val a = 1 / 0 } catch { case e: ArithmeticException => throw new RuntimeException("除数不能为0") case _ => println("other.......") } } 二、scala中的模式匹配功能 类似java中的 switch case 语句,但是比它功能要强大 java switch case 语句: 对值进行匹配 1.7-》String类型匹配 scala的模式匹配: 对值和String的匹配 可以对数据的类型进行匹配 对Array和List集合的元素情况进行匹配 对case class类进行匹配 对有值或无值进行匹配 map.get(key) case .... case ... 模式匹配的语法: 对值的匹配 变量名 match { case 值1 => {方法体} case 值2 => {方法体} case 值3 => {方法体} case _ => {方法体} } 1、在scala中对值的匹配 object MatchDemo1 extends App{ def judgeGrade(name:String,grade:String)={ grade match { case "A" => println(name+",your grade is A ") case "B" => {println(name+",your grade is B ")} case "C" => println(name+",your grade is C ") case _ => println(name+",you need to work harder!!") } } judgeGrade("Lili","E") } object MatchDemo1 extends App{ def judgeGrade(name:String,grade:String)={ grade match { case "A" => println(name+",your grade is A ") case "B" => {println(name+",your grade is B ")} case "C" => println(name+",your grade is C ") case _ if name=="Tom"=>println(name+", come on !!") //对name进行过滤 case _ => println(name+",you need to work harder!!") } } judgeGrade("Tom","E") } object MatchDemo1 extends App{ def judgeGrade(name:String,grade:String)={ grade match { case "A" => println(name+",your grade is A ") case "B" => {println(name+",your grade is B ")} case "C" => println(name+",your grade is C ") case _ if name=="Tom"=>println(name+", come on !! ") case _other => println(name+",you need to work harder,your grade is "+ _other) //可以定义一个变量来获取所匹配变量的值,该变量就可以在后面的方法体被引用,一般变量名定义的规则需要在变量名前面加通配符 } } judgeGrade("mary","E") } 2、scala中对类型的匹配 对类型的匹配语法: 变量名 match { case 变量名:数据类型1 => {方法体} case 变量名:数据类型2 => {方法体} case 变量名:数据类型3 => {方法体} case _ => {方法体} } object MatchDemo2 extends App{ def judgeType(x:Any)={ x match { case x:Int => println("Int........") case x:String => println("String........") case x:Double => println("Double........") case _ => println("other........") } } judgeType("aa") } 3、对集合元素情况的匹配 带有指定元素的集合 带有指定元素个数的集合 以某个元素开头的集合 …… 对Array数组的匹配 object MatchDemo4 extends App { def greeting(arr: Array[String]) = { arr match { case Array("Lio") => println("hi ,Lio !") case Array("Lio",_*)=>println("hi,Lio,please introduce your friends to me ") case Array(a,b,c) => println(a+b+c+",there are 3 students !!") case _ => println("other........") } } greeting(Array("lili","Lio","mary")) } 4、对tuple元组的元素情况匹配 def match_tuple(tuple:Any) ={ tuple match { case (0,_) => println("the first is 0") case (a,0,_) => println("the second is 0 "+a) case _ => println("other.....") } } match_tuple((0,0,3)) 5、对case class类的匹配 case class类: scala中提供了一种以case class声明的类,中文称样例类 类似java-》javaBean,只需要定义字段,在编译时会自动生成getter或setter方法 用途: scala会自动为case class类隐式的定义其伴生对象,并在伴生对象中定义apply方法,这样在new对象时就可以省略关键字new case class类的主构造函数中定义的参数通常可以省略val var修饰,系统会默认使用 val修饰 case class Teacher(name: String, subject: String) case class Student(name: String, classRoom: String) class PP() def judgeID(p: Any) = { p match { case Teacher(name, subject) => println("name:" + name + ",subject:" + subject) case Student(name, classRoom) => println("name:" + name + ",classRoom:" + classRoom) case _ => println("who are you !!") } } judgeID(new PP()) judgeID(Teacher("wang","bigdata")) //因为我们声明的Teacher为case class类,所以不需要使用new 6、模式匹配之对Option的匹配 Option有两个子类,也是其两种值 Some -》代表有值 None-》代表没有值 val grades=Map("zhang"->"A","tom"->"C","Lili"->"B") def getGrade(name:String)={ val grade=grades.get(name) grade match { case Some(grade1)=>println("your grade is "+ grade1) case None =>println("your grade is not in this system!") } } getGrade("mary") 三、高阶函数 scala中函数是一等公民,我们可以将某个函数作为参数传入给其他函数中,接收其他函数作为参数的函数称为高阶函数 def myTest(x: Int, y: Int) = { x * y + 100 } def fun1(f: (Int, Int) => Int, a: Int, b: Int) = { f(a, b) } fun1(myTest, 100, 10) 高阶函数中匿名函数的简化: Array(2,3,5,6).map((x:Int)=>{x*3}) Array(2,3,5,6).map((x)=>{x*3}) Array(2,3,5,6).map((x)=>x*3) Array(2,3,5,6).map(x=>x*3) Array(2,3,5,6).map(_*3) Array(2, 3, 5, 6).filter(_ > 3) Array(2, 3, 5, 6).reduce(_+_) Array(8,2, 3, 5, 6).sorted Array(8,2, 3, 5, 6).sortWith(_>_) Array(8,2, 3, 5, 6).sortWith(_<_) hive hive hive hadoop spark scala flatMap->Array(hive hive hive hadoop spark scala )//拍扁的功能 map->Array(hive hive hive hadoop ) Array(spark scala ) def sayHello(): String = { return "hello!!!!" //在scala如果使用return指定函数的返回值,那么需要显性定义函数的返回值类型 } 四、隐式转换函数 案例一: class SpecialPerson(val name: String) class Student(val name: String) class Older(val name: String) object ImplicitDemo1 extends App { var ticketNm = 0 def buySpecialTticket(spe: SpecialPerson) = { ticketNm += 1 spe.name + "'s ticket number is " + ticketNm } implicit def object2SpecialPerson(obj: Object):SpecialPerson = { //隐式转换函数需要使用implict声明 //隐式转换的函数名称习惯为:被转换类型2目标类型 //隐式转换函数需要显性的定义返回类型 println("***8*888888***") if (obj.getClass == classOf[Student]) { val stu = obj.asInstanceOf[Student] new SpecialPerson(stu.name) } else if (obj.getClass == classOf[Older]) { val old = obj.asInstanceOf[Older] new SpecialPerson(old.name) } else new SpecialPerson("None") } println(buySpecialTticket(new Student("Mary"))) } 案例二: class Man(val name: String) class SuperMan(val name: String) { def emitLaser() = println("emiting laser......................") } object ImplicitDemo2 extends App { val tom=new Man("tom") implicit def man2superman(man:Man):SuperMan={ new SuperMan(man.name) } tom.emitLaser() } 总结: 1、隐式转换函数被调用的时机 当调用某个函数时传入的参数类型和函数定义的参数类型不匹配时 --案例一中 调用的某个类型对象的方法时,这个方法不存在其类中 2、作用域范围 --当前代码作用域范围(当前主函数所在的object对象中) --在源类型(被转换的类型)的伴生对象中 class Man(val name: String) object Man{ implicit def man2superman(man:Man):SuperMan={ new SuperMan(man.name) } } class SuperMan(val name: String) { def emitLaser() = println("emiting laser......................") } object ImplicitDemo2 extends App { val tom=new Man("tom") tom.emitLaser() } --目标类型的伴生对象中,需要手动导入隐式转换函数 import 包名.object类名.隐式转换方法 class Man(val name: String) object SuperMan{ implicit def man2superman(man:Man):SuperMan={ new SuperMan(man.name) } } class SuperMan(val name: String) { def emitLaser() = println("emiting laser......................") } object ImplicitDemo2 extends App { import com.spark.scala.SuperMan.man2superman val tom=new Man("tom") tom.emitLaser() } 五、隐式转换参数 def test(implicit value:String) =println("the value is "+value) test("ABC") implicit val name="tom" test