@[TOC]
1、继承extends
scala使用extends关键字来实现继承。可以在子类中定义父类中没有的字段和方法,或者重写父类的方法。
示例1:实现简单继承
class Person1 {
var name = "super"
def getName: String = this.name
}
class Student1 extends Person1
object Main1 {
def main(args: Array[String]): Unit = {
val p1 = new Person1()
val p2 = new Student1()
p2.name = "李四"
println(p2.getName)
println(p1.getName)
}
}
示例2:单例对象实现继承
class Person2 {
var name = "super"
def getName = this.name
}
object Student2 extends Person2
object Main2 {
def main(args: Array[String]): Unit = {
println(Student2.getName)
}
}
2、override和super
如果子类要覆盖父类中的一个非抽象方法或者属性时,覆盖属性必须要使用override关键字重写一个val字段,覆盖方法再前面加上override。同时可以使用super关键字来访问父类的成员
示例1:class继承class
class Person3 {
val name = "super"
def getName = name
}
class Student3 extends Person3 {
// 重写val字段
override val name: String = "child"
// 重写getName方法
override def getName: String = "hello, " + super.getName
}
object Main3 {
def main(args: Array[String]): Unit = {
println(new Student3().getName)
}
}
3、isInstanceOf和asInstanceOf
我们经常要在代码中进行类型的判断和类型的转换。在Java中,我们可以使用instanceof关键字、以及(类型)object来实现,在scala中如何实现呢?
scala中对象提供isInstanceOf 和 asInstanceOf方法。isInstanceOf判断对象是否为指定类的对象,asInstanceOf将对象转换为指定类型
- | Java | Scala |
---|---|---|
判断对象是否是C类型 | obj instanceof C | obj.isInstanceof[C] |
将对象强转成C类型 | (C) obj | obj.asInstanceof[C] |
获取类型为T的class对象 | C.class | classOf[C] |
例子:
object Main4 {
def main(args: Array[String]): Unit = {
val s1:Person4 = new Student4
// 判断s1是否为Student4类型
if(s1.isInstanceOf[Student4]) {
// 将s1转换为父类Person4类型
val s2 = s1.asInstanceOf[Person4]
println(s2)
}
}
}
4、getClass和classOf
isInstanceOf 只能判断出对象是否为指定类以及其子类的对象,而不能精确的判断出,对象就是指定类的对象。如果要求精确地判断出对象就是指定类的对象,那么就只能使用 getClass 和 classOf 。
对象.getClass可以精确获取对象的类型classOf[x]可以精确获取类型使用操作符可以直接对比
示例:
object Student5{
def main(args: Array[String]) {
val p:Person5=new Student5
//判断p是否为Person5类的实例
println(p.isInstanceOf[Person5])
println(p.isInstanceOf[Student5])
//判断p的类型是否为Person5类
println(p.getClass == classOf[Person5])
//判断p的类型是否为Student5类
println(p.getClass == classOf[Student5])
}
}
5、访问修饰符
Java中的访问控制,同样适用于scala,可以在成员前面添加private/protected关键字来控制成员的可见性。但在scala中,没有public关键字,任何没有被标为private或protected的成员都是公共的。
1、private[this]修饰符
被修饰的成员只能在当前类中被访问。或者可以理解为:只能通过this.来访问(在当前类中访问成员会自动添加this.)。
例子:
class Person6 {
// 只有在当前对象中能够访问
private[this] var name = "super"
var sg = "sg"
def getName = this.name // 正确!
// 传入一个Person6对象
def sayHelloTo(p: Person6) = {
println("hello" + p.name) // 报错!无法访问
}
}
object Person6 {
def showName(p:Person6) = println(p.name) // 报错!无法访问
}
2、protected[this]修饰符
被修饰的成员只能在当前类和当前子类中被访问。也可以理解为:当前类通过this.访问或者子类通过this.
访问示例
class Person7 {
// 只有在当前类以及继承该类的当前对象中能够访问
protected[this] var name = "super"
def getName = {
// 正确!
this.name
}
def sayHelloTo1(p:Person7) = {
// 编译错误!无法访问
println(p.name)
}
}
object Person7 {
def sayHelloTo2(p:Person7) = {
// 编译错误!无法访问
println(p.name)
}
}
class Student7 extends Person7 {
def showName = {
// 正确!
println(this.name)
}
def sayHelloTo3(p:Person7) = {
// 编译错误!无法访问
println(p.name)
}
}
6、调用父类的constructor(构造器)
java实例化子类对象,会自动调用父类的构造器,在scala中,只能在子类的主构造器中调用父类的构造器
示例
class Person8(var name:String){
println("name:"+name)
}
// 直接在父类的类名后面调用父类构造器
class Student8(name:String, var age:String) extends Person8(name)
object Main8 {
def main(args: Array[String]): Unit = {
val s1 = new Student8("李四", "12")
println(s"${s1.name} - ${s1.age}")
}
}
7、抽象类
如果类的某个成员在当前类中的定义是不包含完整的,它就是一个抽象类
不完整定义有两种情况:
1.方法没有方法体
2.变量没有初始化
没有方法体的方法称为抽象方法,没有初始化的变量称为抽象字段。抽象类的定义和Java一样,在类前面加上abstract关键字就可以了
示例
abstract class Person9(val name:String) {
//抽象方法
def sayHello:String
def sayBye:String
//抽象字段
val age:String
}
class Student9(name:String) extends Person9(name){
//重写抽象方法
def sayHello: String = "Hello,"+name
def sayBye: String ="Bye,"+name
//重写抽象字段
override val age:String ="18"
}
object Main9{
def main(args: Array[String]) {
val s = new Student9("Bob")
println(s.sayHello)
println(s.sayBye)
println(s"我${s.age}啦!")
}
}
8、匿名内部类
匿名内部类是没有名称的子类,直接用来创建实例对象。Spark的源代码中有大量使用到匿名内部类。
例子:
abstract class Person10 {
//抽象方法
def sayHello:Unit
}
object Main10 {
def main(args: Array[String]): Unit = {
// 直接用new来创建一个匿名内部类对象
val p1 = new Person10 {
def sayHello: Unit = println("这是一个匿名内部类")
}
p1.sayHello
}
}