Scala入门Part1:基础部分




一、Scala简介

什么是Scala?
  Scalable language,是一种多范式的编程语言。设计初衷是要集成面向对象编程和函数式编程的特性。


二、Scala安装

1.Windows上安装Scala

下载安装包安装完成之后进行环境配置:

右击我的电脑,单击"属性",进入如图所示页面。下面开始配置环境变量,右击【我的电脑】–【属性】–【高级系统设置】–【环境变量】,如图:

在这里插入图片描述

(一)设置SCALA_HOME变量

在这里插入图片描述

(二)设置Path变量

在这里插入图片描述

在"变量值"一栏的最前面添加如下路径:

%SCALA_HOME%\bin;%SCALA_HOME%\jre\bin;

注意:后面的分号 ; 不要漏掉。

(三)设置classpath变量

在这里插入图片描述

"变量值":.;%SCALA_HOME%\bin;%SCALA_HOME%\lib\dt.jar;%SCALA_HOME%\lib\tools.jar.;

注意:"变量值"最前面的 .; 不要漏掉。最后单击确定即可。

(四)检查环境变量

单击 【开始】,在输入框中输入cmd,然后"回车",输入 scala,然后回车,如环境变量设置ok,你应该能看到这些信息。

在这里插入图片描述

2.Linux上安装Scala

确保你本地以及安装了 JDK 1.5 以上版本,并且设置了 JAVA_HOME 环境变量及 JDK 的bin目录。
我们可以使用以下命令查看是否安装了 Java:
java -version
接着,我们可以查看是否安装了 Java 编译器。输入以下命令查看:
javac -version
确保都已安装之后,请下载Scala安装包开始安装。
(一)解压缩、重命名并删除原压缩包
(二)配置环境变量


三、Scala基础

1.基本语法

  • 区分大小写
  • 类名:第一个字母大写
  • 方法名称:第一个字母小写
  • def main(args:Array[String]) - Scala程序从main函数开始处理

2.标识符

有三种方法可以构造一个标识符。

  • 首字符是字母,后续字符是任意字母和数字。这种标识符还可后接下划线‟_‟,然后是任意字母和数字。
  • 首字符是算符字符,后续字符是任意算符字符。这两种形式是普通标识符。
  • 标识符可以是由反引号‟`‟括起来的任意字符串(宿主系统可能会对字符串和合法性有些限制)。这种标识符可以由除了反引号的任意字符构成。

3.数据类型

常用的基本类型有:Byte、Short、Int、Long、Float、Double、Boolean、Char。

与Java不同的是,在Scala中,这些类型都是“类”,并且都是包Scala的成员。比如,Int的全名是Scala.Int。

对于字符串,Scala用java.lang.String来表示字符串。
在这里插入图片描述

4.变量和常量

(一)变量和常量的区别

  • 变量:用var修饰,在程序运行过程中其值可能发生改变。
  • 常量:用val修饰,在程序运行过程中其值不会发生变化。

(二)变量和常量的声明

定义变量或者常量时,返回类型可以省略,如:val a:Int = 10
声明时不一定需要初始值:

var myVar :Int; 
val myVal :String;
  • 在 Scala 中声明变量和常量不一定要指明数据类型,在没有指明数据类型的情况下,其数据类型是通过变量或常量的初始值推断出来的。所以,如果在没有指明数据类型的情况下声明变量或常量必须要给出其初始值,否则将会报错。

val myVal = "Hello, Scala!";

其中,myVar 会被推断为 Int 类型,myVal 会被推断为 String 类型。

(三)Scala多个变量声明

如果方法返回值是元组,我们可以用val声明一个元组:

val (myVar1:Int,myVar2:String) = Pair(40,"foo")

也可以不指定数据类型:

val (myVar1,myVar2) = Pair(40,"foo")

5.运算符

  • 算术运算符:+,-,*,/,%
  • 关系运算符:==,!=,>,<,>=,<=
  • 逻辑运算符:&&,||,!
  • 位运算符:~(取反),&(与),|(或),^(异或),<<(左移),>>(右移)
  • 赋值运算符:=,+=,-=,*= 等

上述运算符的优先级从上到下逐渐降低。

6.类和对象

  • (1)Scala里Object是对象,定义在Object中的变量、方法都是静态的,Object不能传参。
  • (2)Scala里可以定义类,类可以传参数,但是参数必须指定类型和格式。
  • (3)Scala具有推断机制,所一一行语句可以不加分号。
  • (4)Scala里类的定义和构造方法是一起的,如果类没有参数,那么构造方法也是无参的。可以重写构造器,方法是def this,在方法体中第一行要调用默认构造器。
  • (5)Scala中类的属性都默认带有getter/setter方法,但是当变量是val时只有getter方法。
  • (6)实例化一个类时(new),这个类里除了方法的代码都会被执行。
object Test {
      def main(args: Array[String]): Unit = {
        new Dog()
      }
}
    
class Dog{
      def dog(): Unit ={
        println("dog方法")
      }
      println("dog类")
}

输出结果:
在这里插入图片描述

  • (7)代码执行顺序是先执行Object中的代码,再执行类里的代码。
  • (8)默认类、方法、属性都是public修饰的,如果把类中属性设为private,那么Object中就不能引用了,除非将类名和Object名改成一致。
    在这里插入图片描述
    在这里插入图片描述
    这种情况称为伴生类和伴生对象,可以互相访问私有对象。

四、控制语句

1.选择控制

(1)If语句:有布尔表达式及语句块

语法:

if(布尔表达式){
   // 如果布尔表达式为 true 则执行该语句块
}

(2)if - else语句:else内语句块可以在布尔表达式为false时执行

语法:

if(布尔表达式){
   // 如果布尔表达式为 true 则执行该语句块
}else{
   // 如果布尔表达式为 false 则执行该语句块
}

(3)If…else if…else语句:在多个条件判断语句的情况下很有用

语法:

if(布尔表达式 1){
   // 如果布尔表达式 1 为 true 则执行该语句块
}else if(布尔表达式 2){
   // 如果布尔表达式 2 为 true 则执行该语句块
}else if(布尔表达式 3){
   // 如果布尔表达式 3 为 true 则执行该语句块
}else {
   // 如果以上条件都为 false 执行该语句块
}

(4)If…else嵌套语句:在if语句中内嵌入多个if语句

语法:

if(布尔表达式 1){
   // 如果布尔表达式 1 为 true 则执行该语句块
   if(布尔表达式 2){
      // 如果布尔表达式 2 为 true 则执行该语句块
   }
}

2.循环类型

(1)while循环

语法:

while(condition){
   //语句或代码块
}

(2)do…while循环

语法:

do {
   //语句或代码块
} while( condition );

(3)for循环:执行指定次数的循环控制结构

语法:

for( var x <- Range ){
   statement(s);
}
  • <- :生成器,表赋值
  • Range:是一个数字区间表示i to j(包括j),或者i until j(不包括j)
  • i to j:
    在这里插入图片描述
  • i until j:
    在这里插入图片描述

for嵌套循环:用分号;设置多个区间
在这里插入图片描述

for循环集合:
语法:

for( var x <- List ){
   statement(s);
}

List变量是一个集合,for循环会迭代所有集合的元素。

for循环过滤:Scala 可以使用一个或多个 if 语句来过滤一些元素。
语法:

for( var x <- List 
if condition1; if condition2... 
){ 
statement(s);
}

for使用yield:将 for 循环的返回值作为一个变量存储
语法:

var retVal = for{ var x <- List
     if condition1; if condition2...
}yield x

五、函数

1.Scala方法

在这里插入图片描述
方法的返回值类型可以不写,编译器能自动推断出来。
在这里插入图片描述

2.Scala函数

函数在定义的时候不能显式地去定义函数返回值。
函数定义:

def functionName ([参数列表]) : [return type] = {
   function body
   return [expr]
}

如果不写等号和方法主体,那么方法会被隐式声明为“抽象(abstract)”,包含它的类型也是一个抽象类型。

//将传入的两个参数相加
object Example {
  def addInt(a:Int,b:Int): Int ={
    a + b
  }

  def main(args: Array[String]): Unit = {
    println(addInt(1,2))
  }
}

(一)递归函数:函数可以调用它本身

//阶乘
object Example {
  def multiply(a:Int):Int={
    if(a==1){
      return 1
    } else {
      a * multiply(a-1)
    }
  }
  def main(args: Array[String]): Unit = {
    println(multiply(3))
  }
}

在这里插入图片描述

(二)带默认值的函数

Scala 可以为函数参数指定默认参数值,使用了默认参数,你在调用函数的过程中可以不需要传递参数,这时函数就会调用它的默认参数值,如果传递了参数,则传递值会取代默认值。

//带默认值的函数
object Example {
  def main(args: Array[String]) {
    println( "返回值 : " + addInt() );
  }
  def addInt( a:Int=5, b:Int=7 ) : Int = {
    var sum:Int = 0
    sum = a + b

    return sum
  }
}

在这里插入图片描述

(三)可变参数函数

允许指明函数的最后一个参数是重复的,即我们不需要指定函数参数的个数,可以向函数传入可变长度参数列表。Scala通过在参数类型之后使用*来设置可变参数。

object Example {
  def main(args: Array[String]) {
    println(fun(1,2,3,4));
  }
  def fun(elements:Int*):Int={
    var sum = 0
    for (i <- elements){
      sum += i
    }
    return sum
  }
}

在这里插入图片描述

(四)匿名函数

语法:

var inc = (x:Int) => x+1

箭头左边是参数列表,右边是函数体,参数的类型是可省略的,Scala 的类型推测系统会推测出参数的类型。使用匿名函数后,我们的代码变得更简洁了。

  • (1)有参匿名函数
  • (2)无参匿名函数
  • (3)有返回值匿名函数
object Example {
      def main(args: Array[String]) {
        //有参匿名函数
        val value1 = (a:Int) => {
          println("有参匿名函数:"+a)
        }
        value1(1)
    
        //无参匿名函数
        val value2 = () => {
          println("无参匿名函数:"+"hello scala")
        }
        value2()
    
        //有返回值匿名函数
        val value3 = (a:Int,b:Int) => {
          println("有返回值匿名函数:"+(a+b))
        }
        value3(3,4)
	  }
}

在这里插入图片描述

(五)嵌套函数

//嵌套函数求5的阶乘
object Example {
  def main(args: Array[String]): Unit = {
    println(fun(5))
  }
  def fun(num:Int)={
    def fun1(a:Int,b:Int):Int={
      if (a==1){
        b
      } else {
        fun1(a-1,a*b)
      }
    }
    fun1(num,1)
  }
}

在这里插入图片描述

(六)偏应用函数

偏应用函数是一种表达式,不需要提供函数需要的所有参数,只需要提供部分,或不提供所需参数。

object FunClass {
  def main(args: Array[String]): Unit = {
    def log(date :Date, s :String)= {
      println("date is "+ date +",log is "+ s)
    }

    val date = new Date()
    log(date ,"log1")
    log(date ,"log2")
    log(date ,"log3")

    //想要调用log,以上变化的是第二个参数,可以用偏应用函数处理
    val logWithDate = log(date,_:String)
    logWithDate("log11")
    logWithDate("log22")
    logWithDate("log33")
  }
}

在这里插入图片描述

(七)高阶函数

操作其他函数的函数,即可以使用其他函数作为参数,或者使用函数作为输出结果。

//apply() 函数使用了另外一个函数 f 和 值 v 作为参数,而函数 f 又调用了参数 v
object Example {
  def main(args: Array[String]): Unit = {
    println(apply(layout,10))
  }

  def apply(f:Int => String,v:Int) = f(v)

  def layout(x:Int) = "["+x.toString+"]"
}

在这里插入图片描述

(八)柯里化函数

将原来接受两个参数的函数变成新的接受一个参数的函数的过程。新的函数返回一个以原有第二个参数为参数的函数。

首先我们定义一个函数:

def add(x:Int,y:Int)=x+y

那么我们调用的时候应该是:add(1,2)
现在我们变一下形:

def add(x:Int)(y:Int) = x + y

那么我们可以这样应用:add(1)(2),最后结果都是3,这种方式(过程)就叫柯里化。
这个过程实际上是调用两个普通函数,实质是:

def add(x:Int)=(y:Int)=>x+y

接收一个x为参数,返回一个匿名函数:接受一个Int型参数y,函数体为x+y。

val result = add(1) 

返回一个result,那result的值应该是一个匿名函数:(y:Int)=>1+y
所以为了得到结果,我们继续调用result。

val sum = result(2)

最后打印出来的结果就是3。

object Example {
  def main(args: Array[String]): Unit = {
    val s1 = "hello "
    val s2 = "scala"
    println(str(s1)(s2))
  }
  def str(s1:String)(s2:String)={
    s1+s2
  }
}

在这里插入图片描述

3.函数和方法

二者的区别在语义上很小,Scala方法是类的一部分,而函数是一个对象可以赋值给一个变量。即在类中定义的函数就是方法。在函数式编程语言中,函数是“头等公民”,可以像任何其他数据类型一样被传递和操作。
首先定义一个方法,再定义一个函数,然后将函数传递到方法里面
在这里插入图片描述

4.将方法转化为函数

在这里插入图片描述
注意:

  • 方法用def定义,函数用val定义
  • 方法的返回值可以写也可以不写,编译器会自动推断。但是在递归函数或返回值是函数类型时,返回值不能省略,必须标明。
  • 有返回值时可以写return,或者不写,函数最后一行会是返回结果。
  • 如果去掉方法体前面的等号,那么这个方法返回类型必定是Unit的。这种说法无论方法体里面什么逻辑都成立,scala可以把任意类型转换为Unit.假设,里面的逻辑最后返回了一个string,那么这个返回值会被转换成Unit,并且值会被丢弃。

猜你喜欢

转载自blog.csdn.net/qq_39394264/article/details/89282431