https://www.runoob.com/scala/scala-install.html
基本与java类似,但首字符要大写
类型 | 说明 |
---|---|
Byte | -128-127 |
Short | -32768-32767 |
Int | -2147483648-2147483647 |
Long | 64位 |
Float | 32位单精度浮点数 |
Double | 64位双精度浮点数 |
Char | 16位无符号Unicode字符 |
Boolean | true或者false |
Unit | 等同void |
Null | null或者空引用 |
Nothing | 类的最底层 |
String | 字符序列 |
Any | 所有类的超类 |
Scala使用关键词 "var" 声明变量,使用关键词 "val" 声明常量,可以省略类型,会自动检测类型
val name = "song"; // 常量
var age = 18 // 变量
var num:Int = 10 // 变量
属性定义
:类的括号里可以定义参数,但必须指明类型,格式参数名:类型
,可以看到,类似于java的有参构造函数,有了参数就有了构造,默认有set和get方法,只有var变量可以set
方法声明
:def functionName ([参数列表]) : [return type]
class Person(xname:String,xage:Int){ // 类
val name = xname;
val age = xage;
def sayName(): Unit ={ // 方法
println("My name is - " + Lesson_ClassAndObj.name)
}
}
在 Scala 中,是没有 static 这个关键字,但是它也为我们提供了单例模式的实现方法,那就是使用关键字object,object相当于java的单例,定义全是静态的
object Lesson_ClassAndObj {
val name = "static test" // 等同于java中用static声明的属性
def main(args: Array[String]): Unit = { // 主函数
val person = new Person("song", 24) // 对象
println(person.name); // get方法
println(person.age);
// 如果age是var类型 person.age = 18相当于调用set方法
person.sayName() // 调用方法
}
}
class Person(xname:String,xage:Int){ // 类
val name = xname;
val age = xage;
var gender = 'N'; // 也可以var gender : String = _ _表示占位符
def sayName(): Unit ={ // 方法
println("My name is - " + Lesson_ClassAndObj.name);
}
def this(xname:String,xage:Int,xgender:Char){ // 重载构造
this(xname,xage);
this.gender = xgender;
}
}
bject Lesson_ClassAndObj {
val name = "static test"
def main(args: Array[String]): Unit = { // 主函数
val person = new Person("song", 24) // 对象
println(person.name); // get方法
println(person.age);
person.sayName() // 调用方法
val person1 = new Person("kun", 28, 'M'); // 重载构造创建的对象
println(person1.gender);
}
}
override val xc
为重写了父类的字段
继承会继承父类的所有属性和方法,Scala 只允许继承一个父类
var不可以继承
class Person(xname:String,xage:Int){ // 类
val name = xname;
val age = xage;
var gender = 'N';
def sayName(): Unit ={ // 方法
println("My name is - " + Lesson_ClassAndObj.name);
}
def this(xname:String,xage:Int,xgender:Char){ // 重载构造
this(xname,xage);
this.gender = xgender;
}
}
class Person2(override val name:String, override val age:Int, val xaddress :String) extends Person(name,age){
var address = xaddress;
def sayAll():Unit = {
print("name - "+ name+"- age - "+age+"- address - "+address);
}
}
object Lesson_ClassAndObj {
val name = "static test"
def main(args: Array[String]): Unit = { // 主函数
val person = new Person("song", 24) // 对象
println(person.name); // get方法
println(person.age);
person.sayName() // 调用方法
val person1 = new Person("kun", 28, 'M');
println(person1.gender);
val person2 = new Person2("zhang", 16, "guangzhou") // 继承的类
person2.sayName() // 调用父类的方法
println(person2.sayAll())
}
}
当单例对象与某个类共享同一个名称时,他被称作是这个类的伴生对象:companion object。你必须在同一个源文件里定义类和它的伴生对象。类被称为是这个单例对象的伴生类:companion class。类和它的伴生对象可以互相访问其私有成员
默认伴生对象是没有构造参数的,但是我们可以重写apply()方法,当调用有参构造半生对象时,会自动匹配apply()方法
// 私有构造方法
class CompanionTest private(val color:String) {
println("创建" + this)
override def toString(): String = "颜色标记:"+ color
}
// 伴生对象,与类名字相同,可以访问类的私有属性和方法
object CompanionTest{
private val markers: Map[String, CompanionTest] = Map(
"red" -> new CompanionTest("red"),
"blue" -> new CompanionTest("blue"),
"green" -> new CompanionTest("green")
)
def apply(color:String) = {
if(markers.contains(color)) markers(color) else null
}
def getMarker(color:String) = {
if(markers.contains(color)) markers(color) else null
}
def main(args: Array[String]) {
println(CompanionTest("red")) //CompanionTest无参数构造,会匹配apply方法
// 单例函数调用,省略了.(点)符号
println(CompanionTest.getMarker( "blue"))
}
}
object IfElse {
def main(args: Array[String]): Unit = {
var x = 30;
if (x == 10) {
println("X 的值为 10");
} else if (x == 20) {
println("X 的值为 20");
} else if (x == 30) {
println("X 的值为 30");
} else {
println("无法判断 X 的值");
}
}
}
object Circle {
def main(args: Array[String]): Unit = {
for(num <- 1 to 10){ // 1到10,包括10
print(num+"-");
}
println()
for(num <- 1 until(10,2)){ // 10到9,步长为2
print(num+"-")
}
println()
for(num <- 1 to 10 ; if(num % 2 == 0) ; if(num > 5)){ // 可以加判断条件
print(num+"-")
}
println()
// 局部变量
var a = 1
// do 循环
do {
print("Value of a: " + a +"-")
a = a + 1
} while ( {
a < 3
})
}
}
def functionName ([参数列表]) : [return type]
object Method {
def main(args: Array[String]): Unit = {
def max(a:Int,b:Int):Int = {
if(a > b) return a;
else return b;
}
// def max(a:Int,b:Int):Int = {
// if(a > b) a else b;
// }
val result : Int = max(100,20);
println(result)
}
}
递归方法必须指定返回值类型
def fun(num:Int):Int = {
if(num == 1) return 1
else return num * fun(num - 1)
}
println(fun(5))
有参数默认值的方法
def fun(a:Int=10,b:Int=20) = {
a + b;
}
println(fun()) // 不覆盖
println(fun(100,300)) // 全部覆盖
println(fun(100)) // 覆盖a
println(fun(b = 50)) // 覆盖b
def fun(s:String*)={
s.foreach(elem=>{println(elem)})// 两种输出方式
for(string <- s) println(string)
}
fun("zhang","liu","wang")
=>就是匿名函数
def fun = (a:Int,b:Int)=>{
a+b
}
println(fun(1,6))
def fun(a:Int): Int ={
def fun1(b:Int): Int ={
if(b == 1) 1
else b * fun1(b - 1)
}
fun1(a)
}
println(fun(5))
def show(date:Date,log:String)={
println(s"date is $date,log is $log") // s $引用外部的属性
}
def fun = show(date = new Date(),_:String) // _ 占位符
fun("a")
fun("b")
fun("c")
类型指定(Int,Int) =>Int
def fun(f:(Int,Int)=>Int,s:String):String={
val res:Int = f(100,200)
res + ""+s
}
val result = fun((a:Int,b:Int)=>{a*b},"scala")
println(result)
def fun(s:String):(String,String)=>String={
def fun1(s1:String,s2:String):String={
s + s1 + s2
}
fun1
}
println(fun("zhang")("liu","wang"))
def fun(f:(Int,Int)=>Int,s:String):(String,String)=>String={
val a:Int = f(100,200)
def fun1(s1:String,s2:String):String={
s1+s2+s+a.toString
}
fun1
}
val res = fun((a:Int,b:Int)=>{a+b},"hello")("zhang","kun")
println(res)
def fun(a:Int,b:Int)(c:Int,d:Int)={
a+b+c+d
}
println(fun(1,2)(3,4))
object StringTest {
def main(args: Array[String]): Unit = {
val s = "zhang" // 普通字符串
val s1 = "zhang1"
val sb = new StringBuffer(); // 可变字符串
sb.append(s).append("liu")
println(sb)
val i = s.compareTo(s1) // compareTo
println(i)
println(s1.charAt(1)) // 索引
val chars = s.toCharArray // 字符串转数组
chars.foreach(c=>{print(c+" ")})
}
}
object ArrayTest {
def main(args: Array[String]): Unit = {
val array = Array[String]("ab","bc") // 直接赋值
array.foreach(s=>{print(s + " ")})
println()
val array2 = new Array[Int](3) // 先声明再赋值,new不可以省略
array2(0) = 2
array2(1) = 3
array2(2) = 10
array2.foreach(num=>{print(num + " ")}) // 遍历数组
println()
val array3 = new Array[Array[Int]](3) // 二维数组 三行
array3(0) = Array[Int](1,2,3,8)
array3(1) = Array[Int](1,6,2)
array3(2) = Array[Int](8,12,9)
array3.foreach(arr=>{arr.foreach(num=>{print(num+" ")});println()}) // 遍历二维数组
var myList1 = Array(1.9, 2.9, 3.4, 3.5) // 合并数组
var myList2 = Array(8.9, 7.9, 0.4, 1.5)
var myList3 = Array.concat(myList1, myList2)
// 输出所有数组元素
for ( x <- myList3 ) {
print( x + " ")
}
println()
var myArr = Array.range(10,20)// 区间数组
myArr.foreach(num=>{print(num+" ")})
}
}
List
object ListTest {
def main(args: Array[String]): Unit = {
val list = List[String]("hello_java","zhang_kun_song")
list.foreach(s=>{print(s+" ")}) // 遍历集合
println()
println(list(0)) // 通过索引获取
val list3 = ListBuffer[Int]() // 可变List
list3.append(1,2,3)
val list1 = list.map(s => { // 对集合中的每一个元素分割,得到的是泛型为数组的集合
s.split("_") // [hello,java] [zhang,kun,song]
})
list1.foreach(arr=>{arr.foreach(s=>{print(s+" ")});println()})
val list2 = list.flatMap(s => {
s.split("_") // [hello] [java] [zhang] [kun] [song]
})
list2.foreach(arr=>{print(arr + " ")})
}
}
object SetTest {
def main(args: Array[String]): Unit = {
val set = Set[Int](1,2,2,2,3,4,5)
val set1 = Set[Int](4,5)
set.foreach((num)=>print(num+" ")) // set有去重功能
println()
val ints = set.intersect(set1) // 集合差集 也可以 set & set1
val ints1 = set.diff(set1) // 差集
val set2 = mutable.Set[Int](1,2,3) // 可变set
set2.+=(4)
set2.foreach((num) =>{print(num+" ")})
}
}
object MapTest {
def main(args: Array[String]): Unit = {
val map = Map[String,Int]("aa"->20,("b",30),("b",40));
val value = map.get("aa").get // 获取value 20
for(elem <- map){ // 遍历map
println(elem)
}
map.foreach(kv=>{ // 遍历集合
println(kv)
})
val keys = map.keys // 获取所有键值
keys.foreach(key=>{ // 遍历key获取value
val value1 = map.get(key).get
println(s"key == $key,value = $value1")
})
val values = map.values // 获取所有value
val map1 = Map[String,Int]("aa"->20,("b",30),("c",40));
val map2 = Map[String,Int]("aa"->30,("b",40),("c",50));
val map3 = map1.++(map2) // map2替换map1
val map4 = map1.++:(map2) // map1替换map2
val map5 = mutable.Map[String,Int]() // 可变map
map5.put("song",24)
}
}
object TupleTest {
def main(args: Array[String]): Unit = {
// 元组可以存不同类型的元素
val tuple = new Tuple1("zhang")
val tuple2 = new Tuple2("zhang",'C')
val tuple4 = new Tuple4("zhang", false, 'C', 16)
val value = tuple2._1 // ._xx取值
println(value)
val value1 = tuple4._4
println(value1)
val iterator = tuple4.productIterator // 遍历,只能先拿到迭代器
iterator.foreach(value=>{println(value)})
}
}
Scala Trait(特征) 相当于 Java 的接口,实际上它比接口还功能强大
与接口不同的是,它还可以定义属性和方法的实现
一般情况下Scala的类只能够继承单一父类,但是如果是 Trait(特征) 的话就可以继承多个,从结果来看就是实现了多重继承
Trait(特征) 定义的方式与类类似,但它使用的关键字是 trait
trait Audi{
val name = "Audi"
def runAudi(time:Int)={
println(name+"running....."+time)
}
}
trait Benz{
val name1 = "Benz"
def runBenz(time:Int)={ // 实现的方法
println(name1+"running....."+time)
}
def recreate():String // 未实现的方法
}
class Car extends Audi with Benz { // 继承第一个用extends,第二个用with
override def recreate(): String = {
"recreate.."
}
}
object TraitTest {
def main(args: Array[String]): Unit = {
val car = new Car
car.runBenz(10)
car.runAudi(20)
}
}
一个模式匹配包含了一系列备选项,每个都开始于关键字 case。每个备选项都包含了一个模式及一到多个表达式。箭头符号 => 隔开了模式和表达式
case _ 什么都不匹配
可以匹配类型,也可以匹配值
object MatchTest {
def main(args: Array[String]) {
println(matchTest("two"))
println(matchTest("test"))
println(matchTest(1))
println(matchTest(6))
println("偏函数"+myTest("ooo"))
}
def matchTest(x: Any): Any = x match {
case 1 => "one"
case "two" => 2
case y :Int => "scala.Int" // 匹配Int类型
case _ => "no match" // case _ 什么都不匹配,类似 switch 中的 default
}
def myTest:PartialFunction[String,Int] = { // 偏函数相比match没有match了,匹配String,返回Int
case "abc" => 22
case "bcd" => 66
case _ => 84
}
}
使用了case关键字的类定义就是样例类(case classes),样例类是种特殊的类,经过优化以用于模式匹配,默认有get和set(对val类型)方法
object CaseClass {
def main(args: Array[String]) {
val alice = new Person("Alice", 25)
val bob = new Person("Bob", 32)
val charlie = new Person("Charlie", 32)
for (person <- List(alice, bob, charlie)) {
person match {
case Person("Alice", 25) => println("Hi Alice!")
case Person("Bob", 32) => println("Hi Bob!")
case Person(name, age) =>
println("Age: " + age + " year, name: " + name + "?")
}
}
}
// 样例类
case class Person(name: String, age: Int)
}
部分参数
是隐式参数,必须使用柯里化的方式
作用
当调用方法时,不必手动传入方法中隐式参数,Scala会自动在作用域内寻找隐式值并自动传入,所以在一个作用域内不能定义多个类型一样的隐式值
object ImplicitTrans {
def main(args: Array[String]): Unit = {
implicit val name:String = "zhang" // implicit声明隐式值柯里化的方式
def sayName(age:Int)(implicit name:String) ={ //
println(s"$name is student... age = $age")
}
sayName(10)
}
}
作用
实现类中方法的共享
class Red{
def sayWho()={
println("Red Red Red")
}
}
class Green{
}
object ImplicitTest {
implicit def greenToRed(green: Green):Red = { // 隐式函数
new Red
}
def main(args: Array[String]): Unit = {
val green = new Green
green.sayWho()
}
}
上面的例子中,创建了green对象,但我想用Red类中的方法,于是我就声明一个隐式函数,传入green对象,返回一个red对象,就可以调用了
注意:相同作用域内,不可以定义相同的传入参数和返回类型相同的隐式函数
class Dog{
}
object ImplicitClass {
implicit class Animall(dog: Dog){
def sayName(): Unit ={
println("dog隐式类...")
}
}
def main(args: Array[String]): Unit = {
val dog = new Dog
dog.sayName // 创建了一个dog对象
}
}
创建了一个dog对象,调用了sayName方法,但实际类中是没有这个方法的,于是就去找有没有一个隐式类,参数是Dog类型的,有的话就可以调用里面的方法