Scala语言入门

一.Scala安装

https://www.runoob.com/scala/scala-install.html

IDEA创建Scala项目
在这里插入图片描述
在这里插入图片描述

二.类和对象

1.Scala基本数据类型

基本与java类似,但首字符要大写

类型说明
Byte-128-127
Short-32768-32767
Int-2147483648-2147483647
Long64位
Float32位单精度浮点数
Double64位双精度浮点数
Char16位无符号Unicode字符
Booleantrue或者false
Unit等同void
Nullnull或者空引用
Nothing类的最底层
String字符序列
Any所有类的超类

Scala使用关键词 "var" 声明变量,使用关键词 "val" 声明常量,可以省略类型,会自动检测类型

val name = "song";  // 常量
var age = 18  // 变量
var num:Int = 10 // 变量
2.Scala定义类

属性定义:类的括号里可以定义参数,但必须指明类型,格式val 参数名:类型或者var 参数名:类型,可以看到,类似于java的有参构造函数,有了参数就有了构造,默认有set和get方法,只有var变量可以set

方法声明:def functionName ([参数列表]) : [return type]

class Person (){

  var name : String = _
  var age : Int = _

  println("1.父类的主构造器")

  def this(name : String,age : Int){
    this()
    println("2.父类的辅助构造器")
    this.name = name
    this.age = age
  }

  def printInfo() = {
    println(s"Person : $name,$age")
  }
}


class Teacher(name : String,age : Int) extends Person(){

  var address : String = _

  println("3.子类的主构造器")

  def this(name : String,age : Int,address : String){
    this(name,age)
    println("4.子类的辅助构造器")
    this.address = address
  }
    override def printInfo() = {
      println(s"Teacher : $name,$age,$address")
    }
}

object PsersonDemo {
  def main(args: Array[String]): Unit = {
    val jack: Person = new Person("jack", 36)
    println("=============================================")
    val teacher: Teacher = new Teacher("rose", 30, "gz")

    jack.printInfo()
    teacher.printInfo()
  }
}

在这里插入图片描述

枚举类

case class Schedule(name:String)

object Schedule{
  val day = Schedule("day")
  val hour = Schedule("hour")
}
3.Scala单例对象

在 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() // 调用方法
  }
}

在这里插入图片描述

4.伴生对象

作用:实现类似Java中那种既有实例成员又有静态成员的类的功能,这样伴生对象中的属性或者方法就好像加上了一个java中static的关键字那样,可以通过类.属性或者类.method()

1.定义一个class并在这里面实现所有的实例成员

2.添加一个 object ,这个object 要与上面的class同名,然后在这里面实现所有的静态成员,也即伴生对象

3.定义的 class 与 object 必须在同一个文件内

当单例对象与某个类共享同一个名称时,他被称作是这个类的伴生对象:companion object。你必须在同一个源文件里定义类和它的伴生对象。类被称为是这个单例对象的伴生类:companion class。类和它的伴生对象可以互相访问其私有成员

apply()方法会帮助我们免除new关键字

// 普通类
class CompanionTest (val color : String) {

  private val name: String = "Java"

  def out(): Unit = {  // 访问伴生对象的私有属性  object.属性
    println("伴生对象的私有属性: " + CompanionTest.addrss)
  }

}

// 伴生对象,与类名字相同,可以访问类的私有属性和方法
object CompanionTest{

  private val addrss = "gz" // CompanionTest.address  等同于实现了java中的类.属性

  // 伴生类的实例
  private val companionTest: CompanionTest = new CompanionTest("red")


  def out2(): Unit = {
    println(companionTest.name)  // 访问伴生类的私有属性  实例.属性
  }

  def apply(color: String): CompanionTest = new CompanionTest(color)
}


object Test{
  def main(args: Array[String]): Unit = {
    // 免new apply方法
    val test: CompanionTest = CompanionTest("blue")
    println(test.color)
    test.out()
  }
}
5.控制抽象

控制抽象 主要在在一个方法中调用某个代码块 也没有返回值

object OpTest {
  def main(args: Array[String]): Unit = {
    // 柯里化
    def a (name : String)(op : => Unit): Unit ={
      println("我是控制抽象op前的操作" + "名字"+name)
      op
      println("我是控制抽象op后的操作" + "名字"+name)
    }

    // 方法中的代码块将作为op
    a("zhang"){
      println("我是op")
    }
    
  }
}

在这里插入图片描述

三.简单语法

1.if-else
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 的值");
    }
  }
}

在这里插入图片描述

2.循环
  • while 循环 运行一系列语句,如果条件为true,会重复运行,直到条件变为false
  • do…while 循环 类似 while 语句区别在于判断循环条件之前,先执行一次循环的代码块
  • for 循环 用来重复执行一系列语句直到达成特定条件达成,一般通过在每次循环完成后增加计数器的值来实现
  • break 语句 中断循环
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
    })

  }
}

在这里插入图片描述

3.方法

def functionName ([参数列表]) : [return type]

  • 如果有return,则必须指定返回值类型
  • 没有return,默认将最后一行计算的结果当做返回值
  • 传入的参数必须指定类型
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))

在这里插入图片描述

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+" ")})

  }
}

在这里插入图片描述

5.数组
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+" ")})

  }
}

在这里插入图片描述

6.集合

List

实际开发使用ListBuffer较多,创建时不使用new关键字,可以初始化ListBuffer,例如
ListBuffer[String](“kun”,“zhang”)

object ListTest {
  def main(args: Array[String]): Unit = {
    val list: List[String] = List[String]("hadoop", "spark")


    // List添加元素到最前面   注意 List是不可变的,这里只是生成了新的一个List了  List(brfore, hadoop, spark)
    println(list.+:("brfore") )
    // List添加元素到最后面 List(hadoop, spark, after)
    println(list :+ "after")

    val newList = list.+:("before")
    // 连接两个List List(hadoop, spark, before, hadoop, spark)
    println(list ::: newList)


    val list2: ListBuffer[Int] = ListBuffer[Int]()  // 可变ListBuffer
    list2.append(66)  // append添加元素
    list2.append(33,66,66,99) // append批量添加
    40 +=: list2 // +=: 加到前面
    println(list2) // ListBuffer(40, 66, 33, 66, 66, 99)

    list2 -= 66  // -=删除已知元素
    list2.remove(2) // 删除下标为index的元素

    list2.update(3,1000) // 改元素 index,new data
    println(list2(0)) // 根据索引查元素  40
  }
}



Set

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 -= 2
    set2.foreach((num) =>{print(num+" ")})
    println()

  }
}

在这里插入图片描述

Map

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

    var map5 = Map[String,Int]()  // 可变map
    map5 += ("age" -> 20)
    map5 += ("length" -> 40)

    map5.foreach(println)

    val map6 = mutable.Map[String,Int]()  // 可变map

  }
}

在这里插入图片描述
Tuple

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)})

  }
}

在这里插入图片描述

四.常用语法

1.Trait

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)
  }

}

在这里插入图片描述

2.Match

一个模式匹配包含了一系列备选项,每个都开始于关键字 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
  }
}

在这里插入图片描述

3.样例类

当我们定义一个样例类,编译器自动帮助我们实现了apply方法,无需new关键字,而且自动实现了以下的方法

toString方法:可直接调用

equals方法:可以直接使用==比较两个样例类是否相等,即所有的成员变量是否相等

hashCode方法:样例类自动实现了hashCode方法,如果所有成员变量的值相同,则hash值相同,只要有一个不一样,则hash值不一样

copy方法:样例类实现了copy方法,可以快速创建一个相同的实例对象,可以使用带名参数指定给成员进行重新赋值

使用了case关键字的类定义就是样例类(case classes),样例类是种特殊的类,经过优化以用于模式匹配,默认有get和set(对var类型)方法

object CaseClass {
  def main(args: Array[String]) {
    val alice = Person("Alice", 25)
    val bob = Person("Bob", 32)
    val charlie = 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)
}

在这里插入图片描述

4.隐式值与隐式参数
  • 用implicit修饰的值就是隐式值
  • 用implicit修饰参数就是隐式参数,注意,如果方法中部分参数是隐式参数,必须使用柯里化的方式

作用

当调用方法时,不必手动传入方法中隐式参数,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)

  }
}

在这里插入图片描述

5.隐式转换函数

作用

实现类中方法的共享

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对象,就可以调用了

注意:相同作用域内,不可以定义相同的传入参数和返回类型相同的隐式函数

6.隐式类
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类型的,有的话就可以调用里面的方法

  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jumanji_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值