1、Scala基础
1.1 基本数据类型和变量
- Unit类型只有一个唯一值,用空括号表示
- val申明的变量必须在申明时就必须被初始化,初始化以后不能再赋新值
- var申明的变量是可变的可以被多次赋值
1.2 控制结构
- for循环可以对任何类型的容器类进行枚举
for (i <- Array(3,5,6)) print(i)
for (i <- 1 to 5 if i%2==0) println(i)
for (i <- 1 to 5; j <- 1to 3) println(i*j)
- 可以在每次执行的时候创造一个值,然后将包含了所有产生值的容器对象作为for循环表达式结果返回。
val r=for (i <- Array(1,2,3,4,5) if i%2==0) yield { println(i); i}
- scala的break用法
breakable{
for(i<- array){
if(i>5) break //跳出breakable,终止for循环,相当于Java中的break
println(i)
}
}
1.3 数据结构
数组
- 数组Array是一种可变的、可索引的、元素具有相同类型的数据集合,Array[Int] 类似 Int[]
Array.ofDim[Int](3,4)
元组
- 可以返回多个不同类型的对象
val tuple = ("BigData",2015,45.0)
容器(Collection)
-
定义了列表(List)、映射(Map)、集合(Set)几大类
Collection
序列
- 序列是指元素可以按照特定的顺序访问的容器
- List,一旦被定义,其值就不能改变,但是可以赋给新list,::是右结合,Nil不能省略
val otherList="Apache"::strList
val intList = 1::2::3::Nil
- List的可变版本是ListBuffer 如果需要所有访问时间都是常数,可以使用Vector
集合
var mySet = Set("Hadoop","Spark")
mySet += "Scala"
映射
scala> import scala.collection.mutable.Map
scala> val university2 = Map("XMU" -> "Xiamen University", "THU" -> "Tsinghua University","PKU"->"Peking University")
scala> university2("XMU") = "Ximan University"
scala> university2("FZU") = "Fuzhou University"
scala> university2 += ("TJU"->"Tianjin University")
2、面向对象编程
2.1 类
def 方法名(参数列表):返回结果类型={方法体}
class Counter {
var value = 0
def increment(step:Int):Unit = { value += step}
def current():Int = {value}
}
- 不需要return返回,最后一个表达式的值是返回
2.2 对象可见性
- Scala的value和value_类似get和set
class Counter {
private var privateValue = 0
def value = privateValue
def value_=(newValue: Int){
if (newValue > 0) privateValue = newValue
}
def increment(step: Int): Unit = {value += step}
def current():Int = {value}
}
2.3 方法定义
- 无参方法可以不写括号
def current:Int= value
- 如果方法没写括号,调用的时候也不能写括号,如果方法定义时写了,则都可以
2.4 构造器
- 一种是类定义主体
class Counter(name: String) {
private var value = 0
def increment(step: Int): Unit = { value += step}
def current(): Int = {value}
def info(): Unit = {printf("Name:%s",name)}
}
- 一种是适用this,构建辅助构造器,this返回类型为Unit
class Counter {
private var value = 0
private var name = ""
private var step = 1 //计算器的默认递进步长
println("the main constructor")
def this(name: String){ //第一个辅助构造器
this() //调用主构造器
this.name = name
printf("the first auxiliary constructor,name:%s\n",name)
}
def this (name: String,step: Int){ //第二个辅助构造器
this(name) //调用前一个辅助构造器
this.step = step
printf("the second auxiliary constructor,name:%s,step:%d\n",name,step)
}
def increment(step: Int): Unit = { value += step}
def current(): Int = {value}
}
2.5 对象
单例对象
Scala采用单例对象来实现与Java静态成员同样的功能
- 单例对象使用Object进行定义
- 可以就像一个类的实例一样使用
- 定义单例对象不是定义类型,不能实例化
object Person {
private var lastId = 0 //一个人的身份编号
def newPersonId() = {
lastId +=1
lastId
}
}
- 当一个单例对象和它的同名类一起出现,单例对象是这个同名类的伴生对象,需要位于同一个文件下,否则被称为孤立对象
- 伴生对象的方法智能通过伴生对象调用不能通过半生类的实例直接调用
class Person(val name:String){
private val id = Person.newPersonId() //调用了伴生对象中的方法
def info() {
printf("The id of %s is %d.\n",name,id)
}
}
object Person {
private var lastId = 0 //一个人的身份编号
def newPersonId() = {
lastId +=1
lastId
}
def main(args: Array[String]) {
val person1 = new Person("Lilei")
val person2 = new Person("Hanmei")
person1.info()
person2.info()
}
}
apply方法
- 用括号传递给实例或对象名一个或多个参数时,Scala会在相应的类或对象中查找方法名为apply且参数列表相同的方法
val myStrArr = Array("BigData","Hadoop","Spark")
class TestApplyClass {
def apply(param: String){
println("apply method called: " + param)
}
}
scala> val myObject = new TestApplyClass
myObject: TestApplyClass = TestApplyClass@11b352e9
scala> myObject("Hello Apply")// 自动调用类中定义的apply方法,等同于下句
apply method called: Hello Apply
- apply方法的形式定义常被放在伴生对象中,这样伴生对象就像生成类实例的工厂
- 对于方法,也可以使用apply
def add=(x:Int,y:Int)=>x+y //add是一个函数
add: (Int, Int) => Int
add(4,5) //采用数学界的括号调用样式
res2: Int = 9
- update也是一个类似方法,但是是在赋值的时候会被调用
persons("LiLei")=28 // 实际调用了Map的update方法,与下句等效
persons.update("LiLei",28)
unapply
- apply的反向操作,unapply方法接收一个对象,从中提取值,返回一个Option类型
- 比如下面的例子就自动调用了unapply并获取了carband和carprice的值
class Car(val brand:String,val price:Int) {
def info() {
println("Car brand is "+ brand+" and price is "+price)
}
}
object Car{
def apply(brand:String,price:Int)= {
println("Debug:calling apply ... ")
new Car(brand,price)
}
def unapply(c:Car):Option[(String,Int)]={
println("Debug:calling unapply ... ")
Some((c.brand,c.price))
}
}
object TestUnapply{
def main (args: Array[String]) {
var Car(carbrand,carprice) = Car("BMW",800000)
println("brand: "+carbrand+" and carprice: "+carprice)
}
}
2.6 继承
抽象类
abstract class Car(val name: String) {
val carBrand:String // 没有初始化值是抽象字段
def info() // 抽象方法
def greeting() {
println("xxx")
}
}
类的继承
- 只能重载val类型字段,不能重载var类型字段
- 重载父类非抽象字段,必须写override
- 子类的主构造器必须调用父类的主构造器或辅助构造器
abstract class Car(val name:String) {
val carBrand:String //一个抽象字段
var age:Int=0
def info() //抽象方法
def greeting() {
println("Welcome to my car!")
}
def this(name:String,age:Int) {
this(name)
this.age=age
}
}
//派生类,其主构造函数调用了父类的主构造函数
// 由于name是父类主构造器的参数,因此也必须override
class BMWCar(override val name:String) extends Car(name) {
override val carBrand = "BMW" //重载父类抽象字段,override可选
def info() {//重载父类抽象方法,override关键字可选
printf("This is a %s car. It has been used for %d year.\n", carBrand,age)
}
override def greeting() {//重载父类非抽象方法,override必选
println("Welcome to my BMW car!")
}
}
类层级结构
类层级结构- Any类提供了hashCode toString等方法
- AnyVal是所有值类型的父类,值类型不能new
- AnyRef是所有引用类型的父类,引用类型是指实例分配在堆内存,这些实例对应的变量实际是指向了堆中的相应位置
- NULL是所有引用类型的子类,唯一的实例为null,表示一个空对象
- Nothing是所有其他类型的子类,没有实例,用于异常处理函数的返回类型
Option类
- Option类是一个抽象类,有一个具体的子类Some和一个对象None,前者表示有值后者表示没有值
- 使用Option类统一表示对象有值和无值的情况
scala> case class Book(val name:String,val price:Double)
defined class Book
scala> val books=Map("hadoop"->Book("Hadoop",35.5),
| "spark"->Book("Spark",55.5),
| "hbase"->Book("Hbase",26.0)) //定义一个书名到书对象的映射
books: scala.collection.immutable.Map[String,Book] =…
scala> books.get("hadoop") //返回该键所对应值的Some对象
res0: Option[Book] = Some(Book(Hadoop,35.5))
scala> books.get("hive") // 不存在该键,返回None对象
res1: Option[Book] = None
2.7 参数化类型
abstract class Element{
type T //抽象的类型成员
var value:T //抽象的字段,类型为T
def show:Unit //抽象方法,需要根据具体的类型T进行实现
}
class IntEle(var value:Int) extends Element{
type T = Int
def show{printf("My value is %d.\n",value)} //T是Int型时的输出
}
2.8 特质
- 类似于接口,使用Trait标识
- 可以使用extends 也可以使用with 混入特质
trait Flyable {
var maxFlyHeight:Int //抽象字段
def fly() //抽象方法
def breathe(){ //具体的方法
println("I can breathe")
}
}
class Bird(flyHeight:Int) extends Flyable{
var maxFlyHeight:Int = flyHeight //重载特质的抽象字段
def fly(){
printf("I can fly at the height of %d.",maxFlyHeight)
} //重载特质的抽象方法
}
2.9 case类
- Scala为每一个case类自动生成一个伴生对象
case class Car(brand: String, price: Int)
object Car{
def apply(brand:String,price:Int)= new Car(brand,price)
def unapply(c:Car):Option[(String,Int)]=
Some((c.brand,c.price))
}
网友评论