继承
定义一个抽象类,需要使用关键字abstract
定义一个抽象类得抽象方法,不需要关键字,只要把方法体空着
抽象类中定义得字段,没有给初始值得就是抽象字段,但必须声明类型。
abstract class Car{ //是抽象类,不能直接被实例化
val carBrand:String //字段没有初始值,就是一个抽象得字段
def info() //抽象方法,不需要使用abstract关键字
def greeting()=println("welcome to my car!")
}
abstract class person{
var name:String
val age:Int
def show:Int
}
class BMWcar extends Car{
override val carBrand = "BMW" //重写超类字段,需要使用override关键字,否则编译会出错
def info():Unit = println("This is a %s car.It is on sale",carBrand) //重写超类得抽象方法时,不需要使用override关键字,不过如果加上override编译也不错报错
override def greeting():Unit =println("Welcome to my BMW car!") //重写超类的非抽象方法,必须使用override关键字
}
class BYDCar extends Car {
override val carBrand = "BYD" //重写超类字段,需要使用override关键字,否则编译会报错
def info():Unit = printf("This is a %s car. It is cheap.", carBrand)} //重写超类的抽象方法时,不需要使用override关键字,不过,如果加上override编译也不错报错
override def greeting():Unit = println("Welcome to my BYD car!") //重写超类的非抽象方法,必须使用override关键字
}
函数
//定义无输入值的函数
def hi = "hi"
def hi:String = "hi"
def multiplier(x:Int, y:Int):Int = {x*y}
def safeTrim(s:String):String = {
if (s == null) return null
s.trim()
} //来判断输入值是否是非null
过程
没有返回值的函数,以一个语句结尾的函数也是一个过程。如果一个函数,没用显式的返回类型,而且最后是一个语句,scala编译器就会推导出这个函数的返回类型为Unit,表示没用值,对于超过一行的过程,可以显示指定类型Unit。
def log(d:Double) = println(f"Got value $d%.2f") //隐式的返回类型
def log(d:Double) : Unit = println(f"Got value $d%.2f") //显式的返回类型
def log(d:Double) {println(f"Got value $d%.2f")} //这种写法已经废弃了,会报警告
用空括号定义函数
定义和调用一个无输入的函数。
def hi():String = "hi"
hi()
hi
反之,在定义时没用加()。scala就不允许在调用时增加()。
使用函数表达式调用函数
def formatEuro(amt:Double) = f"$amt%.2f"
formatEuro(3.4645)
formatEuro {val rate = 1.32;0.235+0.7123+rate*5.32}
递归函数
调用自身的函数,可能要检查某类参数或外部条件来避免调用陷入无限循环
def power(x:Int, n:Int):Long = {
if (n>=1) x * power(x,n-1)
else 1
}
//添加尾递归优化
@annotation.tailrec
def power(x:Int, n:Int):Long = {
if (n>=1) x * power(x,n-1)
else 1
} //报错
//因为递归调用不是函数的最后一个语句
@annotation.tailrec
def power(x:Int, n:Int):Long = {
if (n < 1) 1
else x * power(x,n-1)
}
/*
现在递归调用的确是函数的最后一项,不过实际上,我们是得到递归调用的结果,然后乘法,所以乘法才是最后一个语句。
*/
@annotation.tailrec
def power(x:Int, n:Int, t:Int = 1):Int = {
if (n < 1) t
else power(x,n-1,x*t)
}
嵌套函数
def max(a:Int, b:Int, c:Int) = {
def max(x:Int, y:Int) = if (x>y) x else y
max(a,max(b,c))
}
//max(Int,Int)嵌套函数在外部函数中使用了两次,局部(嵌套)函数优先于外部函数
用命名参数调用函数
按名调用参数
def greet(prefix:String,name:String) = s"$prefix $name"
val greeting1 = greet("Ms","Brown")
有默认值得参数
def greet(prefix:String="",name:String) = s"$prefix $name" //指定了prefix
val greeting1 = greet(name = "Brown")
Vararg参数
定义输入参个数可变得函数。要标志一个参数匹配一个或多个输入实参,在函数定义中需要改参数类型后面增加一个星号(*)
def sum(items:Int*):Int = {
var total = 0
for (i <- items) total += i
total
}
sum(10,20,30)
sum()
参数组
每个参数组用小括号分隔
def max(x:Int)(y:Int) = if (x>y) x else y
val larger = max(20)(39)
类型参数
def identity(s:String):String = s
def identity(i:Int):Int = i
//如果对想要使用得每一个类型都重新定义函数,就太费劲了。
def identity(a:Any):Any = a
val s:String = identity("Hello") //报错
//使用类型参数定义
def identity[A](a:A):A = a
val s:String = identity[String]("Hello")
val d:Double = identity[Double](2.717)
//类型推导
val s:String = identity("Hello")
val d:Double = identity(2.717)
//
val s = identity("Hello")
val d = identity(2.717)
方法和操作符
方法是类中定义的一个函数,这个类的所有实例都会有这个方法。
val s = "vacation.jpg"
val isJPEG = s.endWith(".jpg")
//s是String的一个实例,String类有一个endWith方法。可以用类名调用也可以用实例名
val d = 65.642
d.round
d.floor
d.compare(18.0)//小于、等于、大于d的值,返回1,0,-1
d.+(2.721)
//操作符
d compare 18.0
d + 2.721
生成API文档的代码
//为函数增加Scaladoc首部
/**
*
*
*/
def safeTrim(s:String):String = {
if (s == null) return null
s.trim()
}