1. Scala中使用模式匹配进行类型判断
在实际的开发中,比如spark源码中,大量的地方使用模式匹配的语法进行类型的判断,这种方式更加地简洁明了,而且代码的可维护性和可扩展性也非常高; 使用模式匹配,功能上来说,与isInstanceOf的作用一样,主要判断是否为该类或其子类的对象即可,不是精准判断。 等同于 java中的switch case语法 ; 代码如下
class Person5 { }
class Student5 extends Person5
object Student5{
def main ( args: Array[ String] ) {
val p: Person5 = new Student5
p match{
case per: Person5 = > println ( "This is a Person5's Object" )
case _ = > println ( "Unknown type!" )
}
}
}
2. Scala中的protected关键字
跟java一样,Scala中同样适用protected关键字 来修饰field和method。在子类中,可直接访问父类的field和method,而不需要适用super关键字; 还可以使用protected[this]关键字 :访问权限的保护范围,只允许在当前子类中 访问父类的field和method,不允许通过其他子类对象访问父类的field和method。 代码如下
class Person6 {
protected var name: String = "tom"
protected [ this ] var hobby: String = "game"
protected def sayBye = println ( "Byebye..." )
}
class Student6 extends Person6 {
def sayHello = println ( "Hello" + name)
def sayByeBye = sayBye
def makeFriends ( s: Student6) = {
println ( "My hobby is " + hobby+ ", your hobby is UnKnown" )
}
}
object Student6{
def main ( args: Array[ String] ) {
val s: Student6= new Student6
s. sayHello
s. makeFriends ( s)
s. sayByeBye
}
}
3. Scala中调用父类的constructor
Scala中,每个类都可以有一个主constructor和任意多个辅助constructor,而且每个辅助constructor的第一行都必须调用其他辅助constructor或者主constructor代码;因此子类的辅助constructor是一定不可能直接调用父类的constructor的 ; 只能在子类的主constructor中调用父类的constructor。 如果父类的构造函数已经定义过的 field,比如name和age,子类再使用时,就不要用 val 或 var 来修饰了,否则会被认为,子类要覆盖父类的field,且要求一定要使用 override 关键字。 代码如下
class
Person7 ( val name: String, val age: Int) {
var score: Double = 0.0
var address: String = "beijing"
def this ( name: String, score: Double) = {
this ( name, 30 )
this . score = score
}
def this ( name: String, address: String) = {
this ( name, 100.0 )
this . address = address
}
class Student7 ( name: String, score: Double) extends Person7 ( name, score)
}
4. Scala中匿名内部类
在Scala中,匿名内部类是非常常见的,而且功能强大。Spark的源码中大量的使用了匿名内部类; 匿名内部类,就是定义一个没有名称的子类,并直接创建其对象,然后将对象的引用赋予一个变量,即匿名内部类的实例化对象。然后将该对象传递给其他函数使用 。代码如下
class Person8 ( val name: String) {
def sayHello= "Hello ,I'm " + name
}
class GreetDemo {
def greeting ( p: Person8) {
def sayHello: String} ) = {
println ( p. sayHello)
}
}
object GreetDemo {
def main ( args: Array[ String] ) {
val p= new Person8 ( "tom" )
val g= new GreetDemo
g. greeting ( p)
}
}
5. Scala中的抽象类
如果在父类中,有某些方法无法立即实现,而需要依赖不同的子类来覆盖,重写实现不同的方法。此时,可以将父类中的这些方法编写成只含有方法签名,不含方法体的形式,这种形式就叫做抽象方法; 一个类中,如果含有一个抽象方法或抽象field,就必须使用abstract将类声明为抽象类,该类是不可以被实例化的; 在子类中覆盖抽象类的抽象方法时,可以不加override关键字; 举例说明:
abstract class Person9 ( val name:String) {
def sayHello:String
def sayBey: String
}
class Student9 ( name: String) extends Person9 ( name) {
def sayHello: String = "Hello," + name
def sayBye: String = "Bye," + name
}
object Student9{
def main ( args: Array[ String] ) {
val s = new Student9 ( "tom" )
println ( s. sayHello)
println ( s. sayBye)
}
}
6. Scala中的抽象字段field
如果在父类中,定义了field,但是没有给出初始值,则此field为抽象field; 代码如下
abstract class Person10 ( val name: String) {
val age: Int
}
class Student10 ( name: String) extends Person10 ( name) {
val age: Int = 50
}