Scala教程

SCALA

第一章 Scala入门

1.1 概述

1.1.1 Scala简介
Scala的全称为Scalable Language,即“可伸缩的语言”,
其设计目标是希望伴随着用户的需求一起成长。
Scala是一门综合了面向对象和函数式编程概念的静态类型的编程语言,
它运行在标准的java平台上,可以与所有的Java类库无缝操作
Spark,Kafka等底层都是Scala编写的
1.1.2 Scala的发展
马丁·奥德斯基    
追求简洁高效
决定将函数式编程语言的特点融合到JAVA中,由此发明了两种语言pizza和scala
JDK5.0泛型、增强for循环、自动类型转换等都是从Pizza引入的新特性
JDK8.0的类型推断、lambda表达式就是从Scala中引入的特性
1.1.3 Scala和Java的关系
Scala基于JVM
参考了Java的思想,可以说是源于Java,Java的进阶版
1.1.4 Scala语言特点
Scala是面向对象的  
每个值都是对象,每个方法都是调用。  
Scala是函数式的   

Scala是功能完整的函数式编程语言,函数式编程以两大理念为指导:
    函数是一等公民
    程序中的操作应该将输入值映射成输出值,而不是当场修改数据。即方法不应该有副作用
以JVM为运行环境的融合语言
面向对象和函数式编程
1.1.5 Scala的优点
与Java兼容
精简的语法
高级语言特性
静态类型

1.2 Scala环境搭建

1.2.1 安装jdk1.8
Spark3.0基于Scala2.12
1.2.2 安装Scala插件
打开IDEA,依次点击Files=>settings=>plungins选项卡,搜索Scala,安装重启即可
1.2.3 创建Scala项目
在IDEA中依次点击File=>New=>Project,然后选择创建Scala-IDEA工程
1.2.4 下载Scala SDK
在上一步中,此时看到Scala为空,依次点击Create=>Download,选择所需版本后,
点击ok进行下载,下载完成点击finish进入工程
1.2.5 创建HelloWorld
在工程src目录上右点击New=>Scala Class创建
选择Scala Object,输入名称完成创建
1.2.6 切换Scala版本
在日常的开发中,由于对应软件,如Spark版本的切换,可能导致需要切换Scala的版本,则
可以在Project Structures中的Global Libraries选项卡中进行切换

1.3 Scala伴生对象

Scala编译后生成两个文件
一个.class文件,一个$.class文件
类叫做伴生对象的声明类
对象叫做类的伴生对象
Hello.class 程序执行的入口类或者当前对象的伴生类
Hello$.class 当前伴生对象的所属类
object
单例对象和伴生对象是为了解决删除静态static关键字之后,而且要实现静态功能而设计的
基于对象来调用,实现完全面向对象

1.4 关联Scala源码

按住CTRL键,~~,将Scala源码下载下来

1.5 官方编程指南

1.在线查看
2.下载解压scala-docs-2.11.8.zip

第二章 变量和数据类型

2.1 注释

和Java一样
单行注释//
多行注释/* */
文档注释/**
        *
        */
代码规范:
    使用Tab键
    Shift+tab缩进
    格式化:CTRL+alt+L
    运算符两边各加一个空格
    一行不超过80个字符
实例:/chapter2/Test01.scala

2.2 变量和常量

Scala的变量分为两种
var 可以被重新赋值
val 不可以修改
var i:Int=10
scala将类型放在后面,表示它的类型并不重要
程序员要关注的东西是变量的名称,业务处理的逻辑
类型是计算机底层需要考虑的问题,跟代码逻辑没什么关系
Scala的编译器是可以对类型自动推断的
能使用常量的地方尽量不使用变量
 * 声明变量时,类型可以省略,编译器可以总动推导
 * 类型确定后,就不能修改,说明Scala是强数据类型语言
 * 变量声明时,必须要有初始值
 * var修饰的可修改,val修饰的不可修改
实例:/chapter2/Test02.scala

2.3 标识符和命名规范

2.4 字符串输出

2.5 键盘输入

2.6 数据类型

Scala中一切数据都是对象,都是Array子类
2.6.1 整数类型

整型分类:

byte,short,int,long
分别是8位,16位,32位,64位
2.6.2 浮点类型
2.6.3 字符类型
2.6.4 布尔类型

2.6.5 Unit类型

Unit表示空值,null类型只有一个实例值null
nothing类型啥也没有:有可能抛出异常,返回值就可以指定为nothing

2.7 类型转换

2.7.1 自动类型转换

自动提升原则:当有多种类型的数值混合运算时,系统首先自动将所有的数据转换成精度大的那种数据类型   
低精度可以赋值给高精度,但反过来不行  
(byte,short)和char之间不会自动相互转换,若要转换,则先转换为int类型  

2.7.2 强制类型转换

将数据由高精度转换为低精度,就需要使用到强制类型转换   
强转换顾好只针对最近的操作数有效,往往会使用小括号提高优先级

2.7.3 数值类型和String类型

1.数值类型转String  
val a:Int=12    
val s:String=a+“” 
2.String类型转数值

第三章 运算符

3.1 算术运算符

+字符串相加

    val re1=10/3  
    println(re1)  
    val re2:Double=10/3  
    println(re2)  
    val re3:Double=10.0/3

3.2 关系运算符

==

3.3 逻辑运算符

&& || !
连接多个条件

3.4 赋值运算符

Scala里面没有++,--等  
可以通过+=,-=等来实现

3.5 位运算符

& | ^ ~ < < >> >>>

3.6 Scala运算符本质

运算符的本质是一个对象的方法调用

    val n1:Int=12  
    val n2:Int=13  
    println(n1.+(n2))

第四章 流程控制

4.1 分支控制

if else 特别的地方:  
有返回值,定义为当前分支最后一个语句的值。
val res=if(age>=18) "成年" else "未成年"

4.2 嵌套分支

年龄18,12,6,35,60

4.3 Switch分支结构

4.4 for循环控制

####4.4.1范围数据循环to
for循环的特性被称为for推导式

    //scala 范围遍历,to不是关键字,而是方法调用 0.to(9)  
    for(i <- 0 to 9)println(i)  
    for(i<- Range(1,10))println(i)  
4.4.2 范围数据循环until
    for(i <- 1 until 10)println(i)  
    for(i<-Array(10,20,30))println(i)  
4.4.3 循环守卫
    for(i<- -1 to 3 if i!=2)println(i)  
4.4.5 循环步长
    //循环步长,by是一个方法,是Range中的一个方法,(1 to 10).by()
    for(i<-1 to 10 by 2)println(i)
    for(i<-13 to 30 by 3)println(i)
    for(i<-13 to 0 by -2)println(i)
    for(i<-1 to 10 reverse)println(i)
    //步长不能为0
    //含笑半步颠
    for(i<-1.0 to 10.0 by 0.5)println(i)
4.4.6 嵌套循环
    //循环嵌套
    for(i<-1 to 10;j<-1 to 3)println(i*j)
4.4.7 循环引入变量
    //循环引入变量
    for(i<- 1 to 10){
      val j=10-i
      println(i,j)
    }
    for(i<-1 to 10;j=10-i)println(i,j)
    //打印输出九层妖塔
    for(i<-1 to 9;j=9-i){
      println(" "* j + "*"*(2*i-1))
    }
4.4.8 循环返回值
val res=for(i<-1 to 10)yield i

4.5 While 和 do…while循环控制

1,在Scala中不推荐使用while循环,while必须在外部定义变量,while没有for循环的得到返回值用法
2.真正的函数式语言没有循环的,

4.6 循环中断

Scala内部控制结构去掉了break和continue

    // 1. 采用抛出异常的方式退出循环 
    try{
      for(i<-0 until 4){
        if(i==3){
          throw  new RuntimeException
        }
        println(i)
      }
    }catch {
      case e:Exception=>    //什么都不做
    }
    // 2. 为了简化,使用Scala中的Breaks类的break方法,实现异常的抛出和捕捉
    Breaks.breakable(
      for(i<-1 to 4){
        if(i==3){
          Breaks.break();
        }
        println(i)
      }
    )
    println("=============")
    import scala.util.control.Breaks._
    breakable(
      for(i<-1 to 4){
        if(i==3){
          break();
        }
        println(i)
      }
    )

第五章 函数式编程

1.面向对象编程

Scala语言是一个完全面向对象编程语言。万物皆对象
对象的本质:对数据和行为的一个封装

2.函数式编程

函数式编程,解决问题时,将问题分解成一个一个的步骤,将每个步骤进行封装(函数),通过调用
当成一个数学题的求解,所有的都是一个表达式求值的过程
真正的函数式编程语言里没有变量,所有的值来了之后都是常量,所以在scala中能用val的地方就用val
解决问题的过程就是不停的求表达式的值的过程
真正的函数式编程的本质是映射表达式求值。
函数式编程,有一个非常好的特性,对于函数而言是不可变的,这就可以做一个分布式的处理
彼此之间没有额外的影响

5.1 函数基础

5.1.1 函数的基本语法
def funcname(x:Int,y:Int):Unit={println(x+y)}
关键字 函数名称    参数      返回类型   函数体
5.1.2 函数的和方法的区别
函数:为完成某一功能的程序语句的集合,称为函数
方法:类中的函数称之为方法
    object Test01 {
      def main(args: Array[String]): Unit = {
        //定义函数
        def sayHi(name:String):Unit={
          println("hi "+name)
        }
        //调用函数
        sayHi("gaio")
    
        //调用对象方法
        Test01.sayHi("gao")
      }
      //定义对象的方法
      def sayHi(name:String):Unit={
        println("hi hi "+name)
      }
    }
5.1.3 函数定义
参数
返回值
5.1.4 函数参数
1.可变参数
2.如果参数列表中存在多个参数,那么可变参数一般放置在最后
3.参数默认值,一般将有参数的默认值
    //1.可变参数
    def f1(str:String*):Unit={
      println(str)
    }
    f1("alice")
    f1("alice","bob")

    //2.如果参数列表中存在多个参数,那么可变参数一般放置在最后
    def f2(str1:String,str2:String*):Unit={
      println(str1,str2)
    }
    f2("alice")
    f2("alice","bob")
    //3.参数默认值
    def f3(str:String="hi"):Unit={
      println(str)
    }
    f3()
    f3("hihihi")
    //4.带名参数
    def f4(name:String="hi",age:Int):Unit={
      println(s"$age $name")
    }
    f4("bob",23)
    f4(age=24,name="hihanpi")
    f4(age=23)
5.1.5 函数至简原则

能省则省 至简原则细节:

//函数至简原则
    def f0(name:String):String={
      return name
    }
    println(f0("hi"))
    //1.return 可以省略,Scala会使用函数体的最后一行代码作为返回值
    def f1(name:String):String={
      name
    }
    println(f1("hi1"))
    //2.如果函数体里面只有一行代码,则可以省略花括号
    def f2(name:String):String=name
    println(f2("hi2"))
    //3.返回值的类型如果能够推断出来,则可以省略(:和返回值类型一起省略)
    def f3(name:String)=name
    //4.如果函数体里有return,则返回类型不能省略
    def f4()={}
    //5.如果函数明确声明Unit,则即使函数体中使用return关键字也不起作用
    def f5():Unit={
      return 1
    }
    println(f5())
    //6.Scala如果期望是无返回值类型,可以省略等号
    def f6(){//有时候被称为过程
      println("hi")
    }
    //7.如果函数无参数,那么小括号可以省略,调用时小括号可以省略
    def f7(): Unit ={
      println("hi")
    }
    f7()
    f7
    //8.如果没有参数列表,那么小括号可以省略,调用时小括号必须省略
    def f8:Unit={
      println("hi")
    }
    f8
    //9.如果我们不关心名称,只关心处理逻辑,那么函数名def可以省略
    (name:String)=>{println("hi")} //匿名函数,lambda

5.2 函数高级

5.2.1 高阶函数
在Scala中,函数地位很高,一方面,我们在代码的任何地方,可以声明定义一个函数,非常灵活
函数作为一个表达式的值,可以有更加高阶的用法:
    函数可以作为值传递
    函数可以作为参数传递
    函数可以作为函数返回值返回
    val fun=(name:String)=>{println(name)} //匿名函数,lambda
    fun("hi")
    //定义一个函数,以函数作为参数输入
    def f(func:String=>Unit)={
      func("hi")
    }
    f(fun)
    f((name:String)=>{println(name)})

    //匿名函数的简化原则
    f((name:String)=>{println(name)})
    //1.参数的类型可以省略,会根据形参进行自动的推导
    f((name)=>{println(name)})
    //2.类型省略之后,发现只有一个参数,则圆括号可以省略;其它情况:没有参数和参数超过1的永远不能省略圆括号
    f(name=>{println(name)})
    //3.匿名函数如果只有一行,则大括号也可以省略
    f(name=>println(name))
    //4.如果参数只出现一次,则参数省略且后面参数可用_代替
    f(println(_))
    //5.如果可以推断出,当前传入的println是一个函数体,而不是调用语句,可以直接省略下划线
    f(println)
5.2.2 匿名函数

匿名函数没有名字(x:Int)=>{函数体}

    //实例操作,定义一个“二元运算”函数,只操作1和2两个数,但是具体运算通过参数传入
    def dualFunctionOneAndTwo(fun:(Int,Int)=>Int):Int={fun(1,2)}
    val add=(a:Int,b:Int)=>a+b
    val minus=(a:Int,b:Int)=>a-b
    println(dualFunctionOneAndTwo(add))
    println(dualFunctionOneAndTwo(minus))
    //匿名函数简化
    println(dualFunctionOneAndTwo((a:Int,b:Int)=>a+b))
    println(dualFunctionOneAndTwo((a,b)=>a+b))
    println(dualFunctionOneAndTwo(_+_))

    println(dualFunctionOneAndTwo(_-_))
    println(dualFunctionOneAndTwo(-_+_))  //b-a
5.2.3 高阶函数案例
5.2.4 函数柯里化&闭包
5.2.5 递归
5.2.6 控制抽象
5.2.7 惰性函数

第六章 面向对象

Scala的面向对象和Java的面向对象思想和概念是一直的,类的概念,对象的概念
Scala又补充了很多的功能

6.1 Scala包

package 包名
Scala包的作用-和Java一样
    区分相同名字的类
    当类很多时,可以很好的管理
    控制访问范围
6.1.1 包的命名
命名规则:只能包含数字,字母,小花仙,小圆点(分隔符),不能使用关键字,不能数字开头
命名规范: com.公司名.项目名.业务模块名.xxx
6.1.2 包说明(包语句)
1.包名和源文件所在路径不要求必须一致
2.花括号嵌套
6.1.3 包对象
在Scala中可以为每个包定义一个同名的包对象,
定义在包对象中的成员,作为其对应包下所有class和object的共享变量,可以被直接访问
package object name{}
6.1.4 导包说明
和Java一样,顶部导入
局部导入,什么时候用,什么时候import
通配符导入_
给包中的类重新起名import java.util.{ArrayList=>JL}
导入相同包的多个函数import java.util.{HashSet,ArrayList}
屏蔽类import.java.util.{ArrayList=>_,_}
注意:
    Scala中三个默认导入:

6.2 类和对象

类:可以堪称一个模板
对象:表示具体的事物
6.2.1 定义类
1.基本语法
[修饰符]类名
6.2.2 属性

6.3 封装

6.1.5 访问权限
Scala中默认访问权限为public,但是Scala中没有public关键字
private为私有权限,只在类的内部和伴生对象中可用
protected为受保护权限,Scala中受保护权限比Java中更严格,同类、子类可以访问,同包无法访问
private[包名]增加包访问权限,包名下其它类也可以使用
6.2.3 方法
6.2.4 创建对象
6.2.5 构造器
和Java一样,Scala构造对象也需要调用构造方法,并且可以有任意多个构造方法
Scala类的构造器包括:主构造器和辅助构造器

基本语法
    class 类名(形参列表){ //主构造器
        //类体
        def this(形参列表){//辅助构造器}
        def this(形参列表){//辅助构造器可以有多个}
    }

说明:
    1.辅助构造器,函数的名称this,可以有多个,编译器通过参数的个数及类型来区分
    2.辅助构造方法不能直接构建对象,必须直接或间接调用主构造方法
    3.构造器调用其它的构造器,要求被调用构造器必须

实例:/chapter6/Test04.scala
6.2.6 构造器参数
说明:
    1.未使用任何修饰符,局部变量
    2.使用var 作为类的成员属性使用,可以修改
    3.使用val 作为类只读属性使用,不能修改

6.4 继承和多态

基本语法:class 子类名 extends 父类名{ 类体 }
Scala是单继承
继承的调用顺序:先调用父类构造器>然后子类构造器
/**
 * 调用顺序
 * 1.父类的主构造器被调用
 * 2.子类的主构造器被调用
 * 3.子类的辅助构造器被调用
 */
子类中如果要覆盖父类中的属性和方法,必须要加override关键字
在scala中,属性和方法都是动态绑定的

6.5 抽象类

6.5.1 抽象属性和抽象方法
1.基本语法
    定义抽象类
        abstract class Person{}//通过关键字abstract标记抽象类
    定义抽象属性 
        var|val name:String//一个属性没有初始化,就是抽象属性
    定义抽象方法
        def hello():String //只声明而没有实现的方法,就是抽象方法
    说明:
        只要存在抽象属性和抽象方法,那么这个类必须定义为抽象类
        定义了一个抽象类,可以不定义任何的抽象属性和方法
        需要子类具体化之后创建 对象才可用
2.继承&重写
    如果父类为抽象类,那么子类需要将抽象的属性和方法实现,否则子类也需要声明为抽象类
    重写非抽象方法血药用override修饰,抽血抽象方法则可以不加override
    子类调用父类的方法使用super关键字
    子类对抽象属性进行实现,父类抽象属性可以用var修饰
        子类对非抽象属性重写,父类非抽象属性只支持val类型,而不支持var
        因为var修饰的为可变变量,子类继承之后就可以直接使用,没必要重写
6.5.2 匿名子类
说明:
    和Java一样,可以通过包含带有定义或重写的代码块的方式创建一个匿名的子类

6.6 单例对象

scala语言是完全面向对象的语言,所以并没有静态的操作,也没有静态的概念。
但是为了能够和Java语言交互,就产生了一种特殊的对象来模拟类对象,称为单例对象。
若单例对象名与类名一致,则称该单例对象这个类的伴生对象
这个类的所有静态内容都可以放置在它的伴生对象中声明
对于object定义的对象,全局只有一份,在底层,编译后生成两个字节码文件
6.6.1 单例对象语法
object Person{
    val contry:String="china" 
}
说明
    单例对象采用object关键字声明
6.6.2 apply方法

6.7 特质(trait)

6.7。1 特质声明
6.7。2 特质叠加
6.7。3 特质叠加执行顺序
6.7。4 特质自身类型
6.7。5 特质和抽象类的区别

6.8 扩展

你可能感兴趣的:(Scala,scala,java,big,data)