Scala 学习

Posted java安卓技术文章分享

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Scala 学习相关的知识,希望对你有一定的参考价值。

首先很奇怪为什么云栖社区不可以上传资料??
Why?

1.强类型语言 弱类型语言
强类型语言:定义对象或变量时,需要指定其归属类型
一旦一个变量类型确定,它所归属的类型不可再变
弱类型语言:定义变量时不用指定变量类型
在程序运行中,可以改变变量的的归属类型
scala变量定义:
var str = "abcd"
java: String str = "abcd"
这样写法不是没有指定str的类型,而是没有显式的指定str的类型,它隐式的从变量值中自动判断
显式写法:
var str:String = "abcd"

2.声明变量有两种修饰符
var: 变量可被重新赋值
val: (常量)不可被重新赋值
在编程过程中,能使用val的地方不要使用var
3.基础数据类型
java基础数据类型,它对应的变量,不是对象,不能通过"."运算符来访问对象的方法
scala对应java的基础数据类型的类型,对应的变量,是对象,可以通过“.”调用对象的属性或方法
4.String类型的字面量
val s1 = "abcd"
val s2 = "ab\"cd"
val s3 = """ab".eo24/.*cd"""

字符串模板嵌套
println(s"name: n a m e , a g e : age")
println(s"name: n a m e , a g e : {age}aa")
println(s"""name: n a m e | a g e : age
| over
| """
| )
5.基础数据类型之间的转换方法

对象.to类型
123.toDouble
"123".toInt
445.33.toString
6.scala中的运算符
scala中运算符不是语法,而是函数(对象)
a+b 等同于 a.+(b)
前者是后者的简写
当一个对象通过点调用其方法的时候,如果该方法只有1个参数,那么点号可以省略 小括号可以省略,对象、方法、参数之间用空格隔开即可
如果方法有多个参数,那么点号可以省略,但是小括号不能省略

==运算符(Java)
String a = new String("abc")
String b = a
a == b

==在scala中方法,这个方法等同于equal方法
val a = new String("abc")
val b = new String("abc")

a == b a.equal(b)

scala中没有基础数据类型的++ --运算符
7.标识符 符合java的规范
类标识符,驼峰式命名首字母大写
变量 方法标识符,驼峰式命名,首字母小写
包标识符,全小写,层级使用点分割

val在scala中虽然定义的是常量,但是,一般都用变量的规则来命名标识符
8.scala注释规则和java一致
9.语句块
java中的语句块全部都是过程,没有返回值,只有方法语句块中用return才能有返回值
scala中大部分的语句块都是有返回值的,而且不需要return
java中语句块的作用主要用来划分作用域
scala中的语句块除了划分作用域之外还可以带返回值

val str1 = "111"
val str2 = {
val str3 = s"${str1}defg"
str3
}
println(str3) --访问不到
scala中语句块的最后一句,就是该语句块的返回值

8.if...else...
scala中的if else语法是有返回值的,因此可以在变量的赋值上就使用if else语法
另外scala中没有三目运算表达式
9.while循环
语句块中是没有返回值的

10.for循环
for也是scala中少数没有返回值的语句块之一
但是scala中也提供了一种方式(yield)让其具有返回值的能力
java for
for(int i=0;i<10;i++){}
scala 的for 更像 foreach
for(String i:slist){}
for(i <- list){}

通过守卫来限定判断条件
for(i <- 1 to times if i%2==0) println(s"2print:$i")

scala里面没有break 也没有continue
1.但是可以使用scala中提供的特殊类型Breaks来实现break
2.通过return 终止整个函数的方式也可以终结循环

11.Unit类型
java里无返回值的方法类型是void
scala中没有void,它使用Unit类型来代替
Unit的实例就是“()”

12 函数定义
函数定义和对象的定义一样,编译器可以通过返回值来自动判断返回值
因此,绝大多数的函数定义,都不写返回值类型
只有一种情况例外:递归函数
def functionName(x:Int,y:Int):Int = {
x+y
}
在scala因为函数是对象,因此它的定义方式有很多

下面的这个函数定义是一个过程函数的定义,过程函数是没有返回值的,即返回值是Unit 
只要函数这么定义它的返回值就是Unit,就算在函数体内return也不会返回结果
def functionName(x:Int,y:Int){
x+y
}
如果定义函数时把函数的类型指定为Unit那么不管该函数的语句块最后一句结果是什么,
该函数的返回值始终是Unit()
13 函数类型
因为scala中函数是一等公民,因此它和对象一样也有自己的类型
因为函数中涉及的类型包括参数的类型,返回值类型,因此函数的类型就用参数类型和返回值类型来共同定义
如:
def plusInt(x:Int,y:Int)={
x+y
}
那么该函数有两个参数都是Int,有一个返回值也是Int,那么在scala中的函数类型描述是:
(Int,Int)=>Int
其中 => 符号分割参数定义(输入)类型 和 返回值(输出)的类型
(Int)=>Int
Int =>Int
(Int,Int)=>Int

14 函数字面量(匿名函数)
函数的字面量也是用=>来进行定义,它左边是参数(输入),右边是返回值(输出)
val plusIntVal:(Int,Int)=>Int = (x,y)=>x+y
val plusIntVal1 = (x:Int,y:Int)=>x+y

15 def定义的函数不可以被当做对象来被传递
val定义的函数可以被当做函数来被传递
val定义的函数名称,后面不加小括号代表的是对函数对象的引用,后面添加小括号代表的是对函数的调用

16 Array是可变(元素可变)的,它和java的数组T[]是对应的
数组是定长的,定义的时候必须指定长度,一旦声明长度不可发生变化

17 ArrayBuffer是变长数组,该类型对象在声明定义时可以不用指定长度,随着程序的运行
可以随意增间该对象的元素

18 List是不可变的元素列表,里面的元素不可更改,长度也不可更改
List具有递归结构(Recursive Structure)和其它类型集合一样,它具有协变性
比方说Student 是 Person的子类
List[Studnt] 也是 List[Person]的子类
<? extends Person>

19 val def lazy定义变量的区别

20 scala的类定义也是使用class关键词后面跟类的名称然后大括号
class Person {}
Java类体内:
属性
静态属性
非静态属性
方法 静态方法
非静态方法

          静态代码块 :类被加载时执行

scala类体内:
属性:非静态属性
方法:非静态方法
非静态代码块 :每一次被实例化的时候都会被执行一次
(class里面的过程代码(代码块),其实就是类的构造方法)

scala中没有static关键词
scala中用Object(单例类)来承担静态的成员定义

在Class定义的属性和方法必须要通过实例化的对象才能调用
在Object里面定义的属性和方法,直接用Object名称就可以调用

scala的成员也可以使用
private 和protected修饰但是没有public

----跟java一致的部分
没有(public):所有其他代码都可以访问
private:只有自己可以访问
protected:只有子类和同包下面的可以访问
----跟java一致的部分
private:只有自己可以访问
除了自己可以访问之外可以额外开放访问权限
protected:只有子类和同包下面的可以访问 
除了子类和同包外也可以额外开放访问权限
21 构造方法
Java构造方法:有默认无参构造方法
自定义构造方法时默认构造方法消失
构造方法可以重载 [public 类名(参数列表){}]
不同的构造方法之间地位是平等的
Scala构造方法:有无参的默认构造方法
构造方法也可以重载
不同构造方法之间地位不平等,每个scala类都只有一个唯一的主构造方法
除了主构造方法之外,所有次构造方法体内都必须直接或间接的调用主构造方法来完成对象的构建
主构造方法的声明是类声明后面来写
次构造方法是写在类体内的,它的名字统一都叫this
所有的次构造方法在方法体内必须先间接或直接的调用主构造方法后才能写自己的构造逻辑代码,构造方法不需要返回值,它返回值是Unit

              构造方法可以使用默认值参数              class ConstructorWithDefault(var attr1:String,var attr2:String = "defaultATTR2",var attr3:Int = 3)
              这样能大大提高构造方法调用的灵活性
              可以通过在主构造方法参数前面加private的方式来讲主构造方法私有化              class ConstructorMainPrivate private(var attr1:String,var attr2:String)

22 单例对象object
单例对象的属性和方法,可以直接通过单例对象的名称来调用,不需要实例化,它本身就是一个对象
23 如果定义一个object和一个class 他们的名称一样如Student,那么在编译成class文件的时候
他们的会共用一个Student.class的文件
这样一个object和class他们互为伴生
在伴生类中可以通过类名调用伴生对象的属性和方法
但是伴生对象不可以调用伴生类的属性和方法

伴生类和伴生对象之间可以相互访问private的成员
但是如果private添加泛型限定则会有额外的限制,如private[this]

24 apply方法在scala中是有特殊作用的方法,它可以直接通过object名称后面加小括号的形式来调用
object Student 在其中定义一个apply方法

Student.apply() ====(等用于) Student()
apply方法和普通方法一样可以被重载

25 抽象类
java抽象类: 不能够被实例化
可以定义属性,可以定义已实现的方法,也可以定义抽象方法
子类必须实现抽象类中所有的抽象方法
scala抽象类:不能够被实例化
可以定义属性,可以定义已实现的方法
可以定义未被初始化的属性,和未被实现的方法
子类必须初始化所有抽象类中未初始化的属性
必须实现抽象类中未被实现的方法
在定义未实现的方法上必须指定返回值类型

            抽象类可以定义构造方法,构造方法上也可以通过var val等修饰符声明属性
            抽象类主构造方法上有属性定义,子类在继承时必须给抽象类的构造方法传值

            在子类被实例化的时候会先调用父类的构造方法再调用子类的构造方法

26 继承
scala中的继承和java一样使用extends修饰符来定义父类和子类之间的关系
子类会从父类中继承访问控制权限内的属性和方法
子类重写父类方法的时候,如果父类是抽象类,重写的方法是抽象方法override关键词可以省略
否则必须写override

27 匿名类
当我们想要实例化一个类型的对象的时候,如果这个类型是一个抽象类,或者是一个接口
而我们又不想重新定义一个类型来继承抽象类或实现接口
这时候我们可以使用匿名类
可以使用
new AbstractType(){
//实现或重写父类的方法
}
28 组合和继承
当我们想定义一个类型,并且希望这个类型具有比较强大的功能的时候
我们可以考虑两种方式:1 继承 操作简单
在功能使用上面,直接调用可访问的属性和方法(不需要实例化父类的对象)

                             继承只能单继承
                             继承侵入性太强,没办法解耦                     2 聚合  操作复杂 会额外写很多代码,比方说接口的定义
                             对功能方法的调用需要通过实例对象来进行

                             可以多方引入,没有单继承出现的问题
                             方便解耦,使用接口来引入想要扩展的类型

29 scala的总父类型是Any
AnyVal相当于java的基础数据类型
AnyRef相当于java中的Object
30 java的接口:interface
常量
未实现的方法
scala的接口:traits
常量
未实现的方法

                     变量 初始化的变量和未初始化的变量
                     已实现的方法

两种语言在定义接口实现类的时候都必须实现全部接口未实现的方法(scala中包含未初始化的变量)

traits可以多实现 而抽象类只能继承一个

trait不可以被实例化

如果一个类要实现多个接口的话,第一个接口前用extends,后面每一个接口前都用with
class ImpClass extends Trait1 with Trait2 with Trait3...
如果一个类既要继承另一个类又要实现多个接口,那么被继承的类写在extends后面,所有的接口前面加with
class ExtendedAndImpClass extends SuperClass with Trait1 with Trait2 ...

trait之间也可以继承,可以被多继承

31 包和引入
scala中引入包(import)的基本用法和java一致,除了导入包下所有类型的时候Java用的是*,scala中用的是_
scala中可以在引入统一个包的时候用一行代码引入多个类型
import java.util.{Date,Random}

scala中可以在任意的地方引入包
在代码块里用import引入包它的作用域就是代码块内
如果在scala文件的最上方引入,那么它在整个文件内都生效

scala中引入的类型的时候可以给类型起别名
import scala.collection.mutable.{Queue=>MutableQueue}

scala还可以使用import的方式类隐藏类型
import scala.collection.immutable.{HashMap=>,}
相当于在当前引入的所有immutable下的类型隐藏HashMap
在使用HashMap的时候就不会发生类名冲突的问题

包的定义基本用法和java一致,同时也有更高级的用法
包的定义可以嵌套,可以和目录不一致

32 包对象
包对象上经常用来定义一个包下可以使用的常量,函数,object等
在使用这些函数和常量时可以无引用的调用,类似 println

一个包下面只能有一个包对象
定义方式:package object name...
包对象所定义的包下的类可以无引用的使用包对象中的属性和方法

包对象定义的包外的类也可以无引用的使用包对象中的属性和方法,但是需要使用import来导入
import com.zhiyou.bd17.oo.packagetest._

33 权限访问控制和包的关系
private或protected是scala中仅有的两个权限控制修饰

private后面可以通过添加中括号的方式来更灵活的进行自己的权限控制
中括号中可以写:
1.伴生对象伴生类可以各自访问私有成员
2.内部类
private[this] -- 限制上述伴生对象访问自己的私有成员
private[类名] -- 
private[包名] -- 扩充包下的类也可以访问自己的私有成员

34 创建maven的scala项目
1.找模板(scala maven archetype) http://docs.scala-lang.org/tutorials/scala-with-maven.html
G:net.alchim31.maven
A:scala-archetype-simple
V:1.5
2.intellj中new--》project--》maven
勾选create from archetype
点击 add archetype按钮
模板下载完之后选择我们添加的模板:net.alchim31.maven:scala-archetype-simple
next
3.填写自己项目的GAV
4.next---next---finish
5.import changens
6.pom中修改
2.11.tools.version>
2.11.8.version>
改成自己的版本

删除:


org.specs2
specs2_ {scala.tools.version} 1.13 test   org.scalatest scalatest_ {scala.tools.version}
2.0.M6-SNAP8
test

删除:

-make:transitive

删除 test.scala.samples下的所有代码

7.打开App程序 右键运行
打印结果 
scala maven就创建成功

在pom中导入mysql驱动
用scala写一个mysql的增删改查


以上是关于Scala 学习的主要内容,如果未能解决你的问题,请参考以下文章

Programming In Scala笔记-第二三章

初学scala4——trait混入

Scala附加列表

scala编程——函数和闭包

详解 Scala 模式匹配

在Scala项目中使用Spring Cloud