Scala --- 面向对象编程之继承

scala和Java一样,使用extends关键字来实现继承

eg1:实现简单继承

class Person1 {
  var name = "super"

  def getName = 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)
  }
}

eg2:单例对象实现继承

class Person2 {
  var name = "super"

  def getName = this.name
}

object Student2 extends Person2

object Main2 {
  def main(args: Array[String]): Unit = {
    println(Student2.getName)
  }
}

override 和 super

  • 如果子类要覆盖父类中的一个非抽象方法,必须要使用override关键字
  • 可以使用override关键字来重写一个val字段
  • 可以使用super关键字来访问父类的成员
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)
  }
}

//输出 : hello, child

isInstanceOf和asInstanceOf :

  • isInstanceOf  判断对象是否为指定类的对象

  • asInstanceOf  将对象转换为指定类型

JavaScala
判断对象是否是C类型obj instanceof Cobj.isInstanceof[C]
将对象强转成C类型(C ) objobj.asInstanceof[C]
获取类型为T的class对象C.classclassOf[C]
class Person4
class Student4 extends Person4

object Main4 {
  def main(args: Array[String]): Unit = {
    val s1:Person4 = new Student4

    // 判断s1是否为Student4类型
    if(s1.isInstanceOf[Student4]) {
      // 将s1转换为Student3类型
      val s2 =  s1.asInstanceOf[Student4]
      println(s2)
    }
  }
}

//输出 : com.jicheng.Student4@47f37ef1

getClass和classOf :

isInstanceOf 只能判断出对象是否为指定类以及其子类的对象,而不能精确的判断出,对象就是指定类的对象。如果要求精确地判断出对象就是指定类的对象,那么就只能使用 getClass 和 classOf

  • 对象.getClass可以精确获取对象的类型    --   p.getClass

  • classOf[x]可以精确获取类型    ---  classOf[Person5]

  • 使用==操作符就可以直接比较   ---   p.getClass == classOf[Student5]

object Student5{
  def main(args: Array[String]) {
    val p:Person5=new Student5
    //判断p是否为Person5类的实例
    println("p.isInstanceOf[Person5] = "+p.isInstanceOf[Person5])//true

    //判断p的类型是否为Person5类
    println(p.getClass == classOf[Person5])//false

    //判断p的类型是否为Student5类
    println(p.getClass == classOf[Student5])//true
  }
}

//输出 : 
p.isInstanceOf[Person5] = true
false
false

访问控制符:

  • private[this]  :  被修饰的成员只能在当前类中被访问  ; 只能通过this. 来访问
  • protected[this]  :   被修饰的成员只能在当前类和当前子类中被访问   ; 当前类通过this.访问或者子类通过this.访问
  • 任何没有被标为private或protected 的成员都是公共的(没有public)

eg1: private使用

class Person6 {
  // 只有在当前对象中能够访问
  private[this] var name = "super"

  def getName = this.name	// 正确!

  def sayHelloTo(p:Person6) = {
    println("hello" + p.name)     // 报错!无法访问
  }
}

object Person6 {
  def showName(p:Person6) = println(p.name)  // 报错!无法访问
}

eg2 : protected 使用

class Person7 {
  // 只有在当前对象以及继承该类的当前对象中能够访问
  protected[this] var name = "super"

  def getName = {
    // 正确!
    this.name
  }

  def sayHelloTo1(p:Person7) = {
    // 编译错误!无法访问
    println(p.name)
  }
}

object Person7 {
  def sayHelloTo3(p:Person7) = {
    // 编译错误!无法访问
    println(p.name)
  }
}

class Student7 extends Person7 {
  def showName = {
    // 正确!
    println(this.name)
   //  正确
    println(name)
  }

  def sayHelloTo2(p:Person7) = {
    // 编译错误!无法访问
    println(p.name)
  }
}

调用父类的constructor

实例化子类对象,必须要调用父类的构造器  ;在scala中,只能在子类的主构造器中调用父类的构造器 ,

如下:class Student8(name:String, var clazz:String) extends Person8(name)

class Person8(var name:String){
  println("name:"+name)
}

// 直接在父类的类名后面调用父类构造器
class Student8(name:String, var clazz:String) extends Person8(name)

object Main8 {
  def main(args: Array[String]): Unit = {
    val s1 = new Student8("张三", "三年二班")
    println(s"${s1.name} - ${s1.clazz}")
  }
}

//输出 :
name:张三
张三 - 三年二班

抽象类:

  • 如果类的某个成员在当前类中的定义是不包含完整的,它就是一个抽象类

  • 不完整定义有两种情况:1.方法没有方法体   2.变量没有初始化

  • 抽象方法、抽象字段、抽象类 : 没有方法体的方法称为抽象方法,没有初始化的变量称为抽象字段。定义抽象类和Java一样,在类前面加上abstract关键字就可以了

//抽象类
abstract class Person9(val name:String) {
  //抽象方法
  def sayHello:String
  def sayBye:String
  //抽象字段
  val address:String
}
class Student9(name:String) extends Person9(name){
  //重写抽象方法
  def sayHello: String = "Hello,"+name
  def sayBye: String ="Bye,"+name
  //重写抽象字段
  override val address:String ="beijing "
}
object Main9{
  def main(args: Array[String]) {
    val s = new Student9("tom")
    println(s.sayHello)
    println(s.sayBye)
    println(s.address)
  }
}

匿名内部类:

匿名内部类是没有名称的子类,直接用来创建实例对象。Spark的源代码中有大量使用到匿名内部类。

abstract class Person10 {
  //抽象方法
  def sayHello:Unit
}

object Main10 {
  def main(args: Array[String]): Unit = {
    // 直接用new来创建一个匿名内部类对象
    val p1 = new Person10 {
      override def sayHello: Unit = println("我是一个匿名内部类")
    }
    p1.sayHello
  }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值