Scala基础

Scala 基础语法

Scala与Java的最大区别是:Scala语句末尾的; 是可选的。

Scala语法注意事项

  • 区分大小写:Scala是大小写敏感的,意味着 Hello 和 hello在Scala中会有不同的涵义
  • 类名: 对于所有的类名的第一个字母要大写。如果需要使用几个单词来构成一个类的名字,每个单词的第一个字母大写
  • 方法名:所有方法名第一个字母小写,驼峰命名
  • 程序文件名:程序文件的名称应与对象名称完全匹配(新版本不需要,但建议保留习惯)。保存文件时,应该保存它使用的对象名称,并追加.scala 为文件扩展名(如果文件名和对象名称不匹配,程序将无法编译)。
  • def main(args: Array[String]): Scala程序从main() 函数开始处理,这是每一个Scala程序的强制程序入口部分。
  • 符号 “$” 开头的标识符为保留的Scala编译器产生的标识符使用,避免使用"$"开头
  • Scala 内部会使用转义的标识符,比如: -> 使用 $clon$minus$greater 来标识。因此,如果需要在java代码中访问 -> 防范,需要使用Scala的内部名称: $clon$minus$greater

Scala 关键字

abstract case catch class def do else extends false final finally for forSom if implicit import lazy match new null object override package private protected return sealed super this throw trait try true type val var while with yield

Scala注释

object HelloScala {
  /*
  多行注释
  */
  def main(args: Array[String]): Unit = {
//   单行注释
    println("Hello Scala")
    // 可以使用; 进行换行,如果一行只有一句,可以不加;
    val s = "hello" ; println(s)
  }
}

Scala 包

// 和java一样,定义在文件头部
package com.supermap
class HelloWorld
// 类似C# ,如:
package com.supermp{
	class HelloWorld
}

Scala数据类型

Scala的数据类型都是对象,也就是说scala没有java中的原生类型。在scala是可以对数字等基础类型调用方法的。

  • Byte
  • Short
  • Int
  • Long
  • Float
  • Double
  • Char
  • String
  • Boolean
  • Unit: 表示无值,和其他语言void等相同。用作不返回任何结果的方法的结果类型。Unit只有一个实例值,写成()
  • Null: null或者空引用,Scala.Null
  • Nothing: Nothing类型在Scala的类层次的最低端;它是任何其他类型的子类型。
  • Any: Any是所有其他类型的超类
  • AnyRef: AnyRef类是Scala里所有引类(reference calss)的基类

多行字符串的表示方法

val foo = """ hello
supermap
"""
val str =
      """hello
        |world
        |string
        |""".stripMargin

Scala变量

变量声明

在Scala中,使用关键词 var 声明变量,使用 val 声明常量

object Variable {
  def main(args: Array[String]): Unit = {
    //    这是常量
    val myVal : String = "String"
    //    这是变量
    var myVar : String ="VarString"
    println(myVal + myVar)
  }
}

变量类型声明

变量的类型在变量名之后等号之前声明。定义变量的语法格式如下:
var VariableName : DataType [ = Initial Value ] 或
val VariableName : DataType [ = Initial Value ]

变量类型引用

    var name = "张三"
    val age = 15
    println(name,age)

在scala中声明变量和常量不一定要指明数据类型,在没有数据类型的情况下,其数据类型是通过变量或者常量的初始值判断出来的。所以,在没有指明变量或者常量情况下,必须给出初始值,否则会报错。

Scala多个变量声明

Scala支持多个变量的声明

	// school和address的值都是“陕西省西安市莲湖区”
    var school, address = "陕西省西安市莲湖区"
    // 使用val声明一个元组
     val info = ("张三", 24, "男", "陕西省西安市")

Scala 访问修饰符

Private
Protected
Public

作用域保护

package bobsrockets{
    package navigation{
   	// [bobsrockets] 表示这个类对包含在bobsrockets包里面的所有类和对象可见,在包 bobsrockets之外的所有代码都不能访问类navigation
        private[bobsrockets] class Navigator{
         protected[navigation] def useStarChart(){}
         class LegOfJourney{
             private[Navigator] val distance = 100
             }
            private[this] var speed = 200
            }
        }
        package launch{
        import navigation._
        object Vehicle{
        private[launch] val guide = new Navigator
        }
    }
}

Scala修饰符

算数运算符

+ 加
- 减
* 乘
/ 除
% 取余

关系运算符

== 等于
!= 不等于
> 大于
< 小于
>= 大于等于
<= 小于等于

逻辑运算符

&& 逻辑与
|| 逻辑或
! 逻辑非

位运算符

& 按位与运算符
| 按位或运算符
^ 按位异运算符
~ 按位取反运算符
<< 左移动运算符
>> 右移动运算符
>>> 无符号右移

赋值运算符

=
+=
-=
/=
%=
<<==
>>==
&=
^=
|=

条件判断

IF…ELSE…

object Test {
   def main(args: Array[String]) {
	    if(布尔表达式){
	   // 如果布尔表达式为 true 则执行该语句块
		}else{
		   // 如果布尔表达式为 false 则执行该语句块
		}
   }
}

if … else if … else

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

if …else 嵌套

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

循环

while循环

   while( true ){
         println( "a 的值为 : " + a );
      }

do…while 循环

  // do 循环
   do{
       println( "Value of a: " + a );
       a = a + 1;
    }while( a < 20 )

for 循环

	for( a <- 1 to 10){
         println( "Value of a: " + a );
      }

循环控制

Scala不支持break或者continue语句。
在scala2.8之后提供了一种循环方式,当在循环中使用 break 语句,在执行到该语句时,就会中断循环并执行循环体之后的代码块。

// 导入以下包
import scala.util.control._
// 创建 Breaks 对象
val loop = new Breaks;
// 在 breakable 中循环
loop.breakable{
    // 循环
    for(...){
       ....
       // 循环中断
       loop.break;
   }
}

方法与函数

方法是类的一部分,函数是一个对象可以赋值给一个变量。在类中定义的函数即是方法。
Scala中的方法跟Java类似,方法是组成类的一部分。
函数则是一个完整的对象,Scala中的函数其实就是继承了Trait类的对象
Scala使用val语句可以定义函数,def语句定义方法

方法声明

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

方法定义

方法由一个def 关键词开始,紧接着是可选的参数列表,一个冒号 : 和方法的返回类型,一个等于号 = ,最后是方法的主体。

def functionName([参数列表)]) : [return type] = {
	function body
	return [expr]
}
// 求和
  def addInt( a : Int, b : Int) : Int = {
    return a + b
  }
// 没有返回值,可以返回Unit, 这个类似于java的void
 def printInfo() : Unit = {
  println("没有返回值")
}

方法调用

// 和java一样,直接调用
functionName(参数列表)
// 使用实例的对象来调用
(instance.)functionName(参数列表)

可变参数

// Scala通过在参数的类型之后放一个型号来设置可变参数(可重复的参数),例如:
  def printString(args: String*) = {
    var i : Int = 0;
    for(arg <- args){
      println(arg + "[" + i + "]")
      i += 1
    }
  }

默认参数值

// scala 可以在定义的时候指定默认参数值
def addInt(a : Int = 1, b : Int = 2) : Int = { return a + b}

偏函数

 def main(args: Array[String]): Unit = {
 	val date = new Date
    val logWithDateBound = log(date, _ : String)

    logWithDateBound("message1" )
    Thread.sleep(1000)
    logWithDateBound("message2" )
    Thread.sleep(1000)
    logWithDateBound("message3" )
 }
def log(date: Date, message: String)  = {
  println(date + "----" + message)
}

指定函数名

addInt(a = 1, b = 2)

匿名函数

// 匿名函数就是 箭头左边是参数列表,右边是函数体
var intc = (x: Int) => x + 1
// 也可以不给匿名函数设置参数
var userDir = () => {}

函数柯里化

// 定义一个函数
def addInt(x: Int, y : Int) = x + y
add(1,2)
// 变形后
def addInt(x: Int)(y: Int) = x + y
add(1)(2)

数组

  // 声明数组
    var  arr : Array[String] = new Array[String](3)
    var ar = new Array[String](3)
    var z = Array("张三","李四","王五")
    arr(0) = "张三"

    var myList1 = Array(1,2,3,4,5,6)
    var myList2 = Array(7,8,9)
    // 合并数组
    var myList3 = Array.concat(myList1,myList2)
    // 遍历数组
    for(i <- myList3.indices){
      println(myList3(i))
    }
    
    // 创建区间数组, 创建10 - 20之间的数组,跨度2
    var myList4 = Range(10, 20 , 2)

    for(i <- myList4.indices){
      println(myList4(i))
      // 打印结果 10 12 14 16 18
    }

Conllection(集合)

List

    var l = List(1, 2, 3,4)

Set

    var s = Set(1,3,5,7)

Map

    var m = Map("one" -> 1, "two" -> 2, "trhee" -> 3)

元组

    var y = (10,"double")

Option

    var o:Option[Int] = Some(5)

Itrator

   var it = Iterator("百度","Google","Runoob")
    while (it.hasNext){
      println(it.next())
    }

类和对象

  • 类是对象的抽象,对象是类的具体实例。类是抽象的,不占内存,对象是具体的,占用存储空间。
  • scala中的类不声明为public,一个scala文件中可以有多个类

继承

  • 重写一个非抽象方法必须用override修饰
  • 只有著构造函数可以往基类的构造函数里面写参数
  • 在子类重写超类的抽象方法时,不需要使用override
class Points(val xc: Int, val yc: Int) {
  var x: Int = xc
  var y: Int = yc
  def move(dx: Int, dy: Int) {
    x = x + dx
    y = y + dy
    println ("x 的坐标点 : " + x);
    println ("y 的坐标点 : " + y);
  }
}
// Locations 继承 Points。override xc重写父类字段
class Locations(override val xc: Int, override val yc: Int,
               val zc :Int) extends Points(xc, yc){
  var z: Int = zc
  def move(dx: Int, dy: Int, dz: Int) {
    x = x + dx
    y = y + dy
    z = z + dz
    println ("x 的坐标点 : " + x);
    println ("y 的坐标点 : " + y);
    println ("z 的坐标点 : " + z);
  }
}
object Test {
  def main(args: Array[String]): Unit = {
    val loc = new Locations(10, 20, 15);
    // 移到一个新的位置
    loc.move(10, 10, 5);
  }
}

单例

  • scala没有static关键字,使用关键字object关键字
  • 使用单例,除了定义类之外,还要定义一个同名的object对象,它和类的区别时,object对象不能带参数
  • 单例对象和某个类同名时,被称为类的伴生对象,必须在同一个源文件中定义类和它的半生对象。类被成为单例对象的伴生类:companion class。类和伴生对象可以互相访问私有成员

class Markers private( val color: String){
  override def toString: String = "颜色标记:"+ color
}

// 伴生对象
object Markers {
  private val markers: Map[String, Markers] = Map("red" -> new Markers("red"), "green" -> new Markers("green"))
  def apply(color: String) = {
    if(markers.contains(color)) markers(color) else null
  }
  def getMarkers(color: String) = {
    if (markers.contains(color)) markers(color) else null
  }

  def main(args: Array[String]): Unit = {
    println(Markers("red"))
    // 单例调用,省略了.(点)符号
    println(Markers getMarkers("green"))

  }
}

Trait(特征)

  • 相当于java的接口,比接口的功能强大
  • 可以定义属性和方法的实现
  • 一般情况下scala的类只能继承单一父类,但是如果时Trait(特征),可以继承多个,从结果来看就是实现了多重继承
  • trait定义的方法和类类似,使用的关键字时trait
package com.supermap.scala

trait Equal {
  // isEqual 没有定义方法的实现
  def isEqual(x: Any): Boolean
  // isNotEqual 定义方法实现
  def isNotEqual(x: Any): Boolean = ! isEqual(x)
}


class PointInfo(xc: Int, yc: Int) extends Equal {
  var x: Int = xc
  var y: Int = yc
  
  // isInstanceOf 判断是否为指定类型
  // asINstanceOf  将对象转换为指定类型
  override def isEqual(obj: Any): Boolean =
    obj.isInstanceOf[PointInfo] &&
    obj.asInstanceOf[PointInfo].x == x
}


object TestEqual {
  def main(args: Array[String]) {
    val p1 = new PointInfo(2, 3)
    val p2 = new PointInfo(2, 4)
    val p3 = new PointInfo(3, 3)

    println(p1.isNotEqual(p2))
    println(p1.isNotEqual(p3))
    println(p1.isNotEqual(2))
  }
}

模式匹配

  • 一个模式匹配包含一系列备选项
  • 使用箭头符号 => 隔开模式和表达式
  • 每个都开始于case
  • 对应于java的switch case语句
  • 表达式通过代码编写的先后顺序来尝试每个模式来完成计算,只要发现有一个匹配的casae,剩下的case不会继续匹配
  • 构造器的每个参数都成为val,除非显式声明为var,不推荐
  • 伴生 对象提供了apply方法,所以可以不用new构建对象
  • 提供unapply方法使模式匹配可以工作
  • 生成toString、equals、hashCode和copy方法,除非显示给出这些方法的定义
object MatchTest {
  def main(args: Array[String]): Unit = {
  	// 输出结果  : three
    println(matchTest(3))
  }

  def matchTest(x : Int) : String = x match {
    case 1 => "one"
    case 2 => "two"
    case 3 => "three"
  }
}

case class 样例类

object Test {
   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.util.matching.Regex 支持正则表达式
  • Scala的正则表达式继承了java的 语法规则
object MatchingTest {
  def main(args: Array[String]): Unit = {
  	// 使用r() 方法构造一个Regex对象
    val pattern = "Scala".r
    val str = "Scala is Scalable and cool"
    // 使用findFirstIn 找到首个匹配
    println(pattern findFirstIn str)
  	
    val pattern = new Regex("abl[ae]\\d+")
    val str = "ablaw is able1 and cool"
    // mkString方法连接正则表达式匹配结果字符串
    println((pattern findAllIn str).mkString(","))
  }
}

异常处理

  • 异常处理和java类似
  • 抛出异常使用throw方法
  • 异常捕捉的时候,catch字句按照顺序捕捉。在catch中,越具体的异常越靠前。如果抛出的异常不在catch字句中,则无法处理,会被升级到调用者处
  • 捕捉异常的catch子句借用了模式匹配的思想来做异常的匹配
object ExceptionTest {

  def main(args: Array[String]): Unit = {
    try {
      val f = new FileReader("input.txt")
    }catch {
      case es: FileNotFoundException => {
        println("Missing file exception")
      }
      case ex: IOException => {
        println("IO Exception")
      }
    }finally {
      println("Exiting finally...")
    }
  }
}

提取器(Extractor)

  • 提取器式从传递给它的对象中提取出构造该对象的参数
  • Scala标准库包含了一些预定义提取器
  • Scala提取器是一个 带有unapply方法的对象
object ExtractorTest {
  def main(args: Array[String]): Unit = {
    println("Apply 方法 : " + apply("Zara", "gmail.com"))
    println("Unapply 方法 : " + unapply("Zara@gmail.com"))
    println("Unapply 方法 : " + unapply("Zara Ali"))
  }
  // 注入方法 (可选)
  def apply(user: String, domain: String) = {
    user +"@"+ domain
  }

  // 提取方法(必选)
  def unapply(str: String): Option[(String, String)] = {
    val parts = str split "@"
    if (parts.length == 2){
      Some(parts(0), parts(1))
    }else{
      None
    }
  }
}

I/O

  • Scala的文件写操作,直接用的java的I/O类
  • 从屏幕上读,用scala.io.StdIn.readLine()方法
  • 从文件上读,使用scala的Source类及伴生对象来读文件
object IOTest {

  def main(args: Array[String]): Unit = {
  	//写操作,直接用的java的I/O类
    val writer = new PrintWriter(new File("test.txt"))
    writer.write("test")
    writer.close()

    println("请输入姓名")
    // 从屏幕上读,用scala.io.StdIn.readLine()方法
    val line = StdIn.readLine()
    println(line)

      // 从文件上读,使用scala的Source类及伴生对象来读文件
    println("文件内容为")
    Source.fromFile("test.txt" ).foreach{
      print
    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

会灭火的程序员

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

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

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

打赏作者

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

抵扣说明:

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

余额充值