scala

余生颓废 提交于 2019-12-22 20:55:22

Scala

多范式编程语言

运行流程

类Java,先用scalac编译为.class字节码文件,然后再用scala执行出结果,也可用Scala直接运行,不会产生字节码文件,Scala也是依靠jvm来进行编译的

main入口函数

Scala为了简化编程过程,main入口函数和Java的入口函数类似,Scala中是以object伴生对象来代替class,Scala中的所有都是public的,所以不用再次声明public,Scala中用def模拟静态语法,Scala中注重完全面向对象,所以是先声明参数名,再定义参数类型:参数名:参数类型。Java中的定义参数为:参数类型:参数名,返回值类型用unit代替void,用=连接方法体

def Main (参数名:参数类型(可省略)):unit = {方法体}

Scala中的变量

可以用val或var定义,var的值可变,val的值不可变(不可变是因为用final定义的字符串是存放的地址不可变,但是内容可变,用反射可以绕过编译流程,改变字符串内容,大多数情况下Scala中的变量用val定义)

Scala中类型

Scala中的函数类型可以省略,因为Scala是强类型转换,所以定义的类型是不可变的,Scala中不存在基本类型,但是Scala中分为值类型和引用类型,Scala中的值类型和Java中的基本类型用法是相同的且均有8个,在数据进行类型转换的时候都是从小精度的类型开始转换

scala中的for循环

在Scala中的for循环不需要;分割,for(i<-1 to 5)是闭合,to闭合包括5,for(i<- 1 until 5),until前包后不包,实现Java中一次执行的范围在Scala中用Range实现,for(i <- Range(start,end,step)),step代表步长,在Scala中每个函数都是有返回值的,for循环的默认为unit
foreach在Scala中使用yield关键字,将计算得出的结果,放入集合中
循环守卫在Scala中没有continue的关键字,于是使用了叫循环守卫的if判断条件来跳出循环
break:和Java中的break不同,Scala需要导入一个breaks的类,用breaks类来调用break方法,即可实现方法的跳出,但是仅仅使用break跳出的不仅仅是循环体,会直接抛出异常终止编译,为了达到和Java中类似的方法,故用breaks调用breakable方法来捕获异常并且处理,即达到了仅仅跳出循环体的操作

函数式编程

面向对象编程是将问题分解成一个一个小问题,按照对象的解决思维处理问题
函数式编程只关心问题解决的方案,重点在解决使用的函数、函数的入参、出参
可变参数:当有多个需要传值,就需要在参数表中声明多个,为了方便,只需要类型后边加*(name:String*),即可直接在方法中传入多个值
默认参数在Java中当需要对一个参数进行多次调用但是不想重写方法,只需要对方法进行重载,改变需要改变的值即可使用;在Scala中没有提供方法的重载可以直接在参数列表中定义参数时直接对参数进行赋值,即给参数赋了默认值(name:Int= “zhangsan”);当参数调换位置之后,按照传参的匹配规则,就会报错,我们可以使用带名参数在后面给参数进行赋值
函数做返回值:函数做返回值的时候,因为在Scala中直接调用的话,会直接返回出该函数的值或结果,但是如果是返回函数,则需要用——(下划线)来标识,函数柯里化延长了外层函数值的生命周期,为了编程的简便,于是可将多个函数都放在函数列表中(闭包
函数做参数:需要在声明函数时,在函数的参数表中定义函数

def test(f : (入参)=>出参)

即可在该函数中调用具体的函数,但是因为调用函数的时候需要多定义一个函数,为了简便,于是有了匿名函数(()=>{函数逻辑})
惰性函数:按照编译流程,编译器是从上往下编译,先执行上面的结果后执行下面的,有时上面的语句结果暂时不需要,如果执行了又会占用内存空间,于是使用lazy的关键字标注,让不需要的语句延迟执行
trycatch在Scala中也会有捕捉异常的时候,框架类似于Java,但是在声明内部语句的时候,Scala又采用类似Java中switch的case语句,列出错误类型,当有满足条件的语句,就直接返回,不会往下进行

case ex:....错误类型

package在Java中包仅仅起到了包装的作用,但是Scala中包可以嵌套使用,包的路径可以和类路径位置不同,为了限定包的使用范围,在Scala中包也可以使用{},但是在包中只能够声明类,但是无法声明属性和函数,为了改善这一点,于是Scala中又增加了一个包对象,在包对象中就可以声明属性和函数了;如果包起的名字恰好和程序提供的包相同,Scala则不能识别,只会从自己命名的地方找,为了找到提供的包,可以用(root)来区分
example(自己命名的包为package Java和package util,在后面调用Java.util.date则找不到,我们就需要在需要调用的时候加全路径
root.java.util.date即可找到)
import:Java中的import导入的是某一个类,如果需要包中的所有类用Java.util.* ,在Scala中import导入一个类的位置可以在任意地方使用,当导入一个包中的所有类不能用(*),用Java.util.来导入所有类,如果是导入包中的几个类则使用Java.util.{类名}(在花括号中声明要导入哪些类),有时,因为导入了几个相似的类(类名相同包名不同,Scala不能识别),就需要给Scala进行指定,用全路径或者暂时隐藏其他类用(类名=>
属性:在Scala中的属性根据关键字的不同其底层实现也是不同的,当变量声明为var,类声明属性为私有的的,但是在底层会提供公共的getter和setter方法,供类调用,但是变量声明为val,声明后的值在后期是不允许改变的,在类中声明,在底层是用final修饰,赋值后便不能修改,所以只提供了getter方法没有setter方法,若变量用private修饰,和Java一样在外部均不允许访问,
访问权限:在Scala中没有public的关键字,因为Scala中默认所有的均为public,private私有的,在Scala中和Java一样,只能在当前类中访问,protected,在Scala中只有该类的子类可以访问,default,在Scala中又称为包访问,只有在这个包中才可以访问这个类,定义为private[包名]
函数和方法:函数和方法的功能是相同的,但是作用域 却不同,函数可以在任意地方声明或定义,但是方法只能在类中声明
伴生类和伴生对象: Scala中可以同时创建class和object的类型,当class和object的名称相同时,class称为伴生类(成员),object称为伴生对象(静态),伴生对象可以用特殊的方法(apply)创建伴生类的对象,伴生类中可以直接调用在伴生对象中创建的对象,伴生对象可以访问伴生类的私有对象
构造方法:类后是主构造方法,主构造方法内是辅助构造方法,构造方法内的类型不同
:类可以声明为抽象类,用关键字(abstract)修饰,在抽象类中只有抽象方法,当抽象类被继承,继承抽象类的类就需要重写抽象方法(只有声明没有实现的方法),Scala中的抽象方法不用abstract修饰,重写抽象方法只需要补全抽象方法即可
动态绑定机制:在Scala中也可对成员方法进行重写,在重写的时候,需要用override关键字来标识,标识完之后再子类和父类中均有该成员方法,当在主类中调用的时候就会出现问题,到底调用的是子类的方法还是父类的方法,所以引出了动态绑定机制,就是成员方法被重写之后,编译器就会查看主类调用的方法中是否有该方法,如果有就使用子类的(子类中即使没有显式的写出也是有这个方法的,因为子类继承了父类的方法),如果想要使用父类中的方法,就有了多态,使用(super或者this)来明确的指明调用子类还是父类的方法;在Java中不可对属性进行重写但是在Scala中却可以对属性进行重写,因为Scala中的属性也可被看作是方法,在Scala中的抽象属性是只声明却不用等号显式的赋值,在子类中重写属性的时候只需要将它补全即可(在底层的编译中,会产生一个抽闲方法,却不产生抽象属性);当对属性进行重写的时候,也需要用override关键字进行修饰,但是该属性只能是val不可变的
父类的参数:当父类的方法中有参数的时候,子类直接继承即会报错,在Scala中的解决方法是1.可以在extends后的父类直接加参数2.通过子类的传值,从子类中给值然后再传给父类,当在声明类的时候,给这个类给了参数(var/val 参数名 : 参数类型)可在这个类的外部对其进行调用,但是给类的参数没有声明( 参数名 : 参数类型)则不可以在外部调用
特质在Scala中没有接口的类型,但是有类似接口的特质(trait),和Java中的接口不同,特质不许需要实现,也是继承,当同时有父类和特质时,也是继承父类,用with连接特质,多个特质也是用with连接
在Scala中特质可执行代码块,属性和方法均可以声明和调用,当特质和继承同时使用时,特质和父类无关系,只和当前类有关,相同的特质只执行一遍;一个类实现多个特质的时候,特质的代码执行是从左向右,方法执行是从右向左,但是Scala中的super关键字不是指代父类的方法,而是上一级特质,当需要用super指代特定的特质,就需要用(super[父类名]),当对一个类不改变代码,但又需要扩展时,可在构建对象的时候加with动态混入
获取类信息 Scala中用classof[类名],给类起别名用type
隐式类型转换:Scala中为了扩张功能,且不违背ocp原则,提供了implicit关键字 ,在类声明的时候用implicit关键字可以自定义类型的转换,为了可以动态的修改类参数,可将参数定义为implicit类型,即可在外部进行复制,但是不能有多个,Scala不能自行区分,在调用时不能加小括号,在编译的时候,会优先找是否有隐式值;为了扩张类的功能,Scala提供了隐式类,用implicit修饰,在参数中声明相关类的名称,即可以扩展类的功能,但是参数只能有且只有一个
数组:Scala中的数组声明方法和Java中的不同,Scala中,分为可变数组和不可变数组两大类,声明数组的时候用小括号不是方括号。
Array[String()],输出数组的方式有多种,1.可用mkstring增加分隔符输出,2.也可用foreach输出,3.也可用匿名函数的方式直接输出,Array是不可变数组,但是其不可变是指地址的不可变,但是内容可变,先Array数组中添加元素用(:+),冒号是靠近数组的那边,指加在数组前还是数组后;删除元素用delete;ArrayBuffer:是可变数组,增加元素用insert方法,输出和Array类似,移除元素用remove方法,指明移除的位置;可变数组和不可变数组均可互相转换,不可变转可变用toBuffer,可变转不可变用toArray。set和map:的使用和Array类似,map声明键值对的时候是用(“k”->v)来声明的,集合的增加和减少均可以用特殊符号(+、-)来进行
tuple:在使用过程中经常需要将没有关系的数值放到一起使用,就用到了tuple,用小括号将两个值括起来,就是声明了一个元组,元组也可以认为是map中的k-v对,当需要访问元组中的数据时,使用(类名._1)顺序访问
常用函数:sum(求和)、max(最大值)、min(最小值)、product(乘积)、reverse(反转)、groupby(分组)、sortby(根据已给的逻辑排序)、sortwith(用某种逻辑排序)、take(取一定数量的值)、iterator(迭代、遍历)、map(类型的转换、映射)、flatmap(扁平化)、filter(筛选)、zip(拉链匹配、两个集合相同位置结合到一起形成元组)、union(联合两个集合)、intersect(交集)、diff(差集)
聚合减少数据量reduce:可以自己定义将集合中的数据合并为一个,有reduceleft和reduceright;fold:类似reduce,fold增加了集合外的元素,可使用集合外的元素和集合内的元素进行合并,在方法定义的时候用到了函数柯里化
模式匹配:和Java类似,Scala中提供的是match,判断条件放在match之前,用case区分各个条件,有一个条件满足条件便直接跳出,不会执行后续(Java中不一样,如果没有break会全部执行),如果没有匹配的值Scala中是用case下划线来代替Java中的default,在case的后面可直接输入代码块,用(=>)连接。
== 泛型==泛型是对类型的约束,Java中的泛型的类型是不可变的,泛型只能对后续的类型起作用,具有泛型的作用范围,Scala中的泛型可以在方法处加方括号来标识泛型

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!