07_Scala_OOP中_封装_继承_多态_超类

举报
alexsully 发表于 2021/04/08 14:06:30 2021/04/08
【摘要】 1 继承 2 Scala中类型检查和转换 isInstanceOf asInstanceOf 3 超类 只有主构造器可以调用父类的构造器。辅助构造器不能直接调用父类的构造器

1 继承(代码复用) 当多个类存在相同的属性(变量)和方法时, 可以从这些类中抽象出父类

 Scala基本语法

 class 子类名 extends 父类名  {
 类体 
}

 Scala继承好处
1 提高代码的复用性 
2 提高 代码的 扩展性 和 维护性 【当我们修改父类时,对应的子类就会继承相应的方法和属性,不想暴露可以做成私有的】

 Scala重写方法

说明: 重写一个非抽象方法需要用 override修饰符,调用超类(父类/父类的父类)的方法使用super关键字  

def main(args: Array[String]): Unit = {
    val sub = new sub()
    sub.sayHello()
    //sub.test200() //编译器不让过. 同包也不能访问,子类中访问(编译器控制,编译后是public,但是编译前语法禁止)

    println("******")
    sub.test1()
  }

}


class Base {
  var n1: Int = 1 //  public int n1() ; public void n1_$eq(int x$1)
  protected var n2: Int = 2  //  public int n2();  public void n2_$eq(int x$1)
  private var n3: Int = 3 // private int n3() ,  private void n3_$eq(int x$1)  内部和伴生对象中可用

  def test1(): Unit = { // 默认 public void test1()
    println("base 100")
  }

  protected def test2(): Unit = { // public void test2()
    println("base 200")
  }

  private def test3(): Unit = { // private void test3() //private为私有权限,只在类的内部和伴生对象中可用
    println("base 300")
  }
  def sayHi(): Unit = {
    println("sayHi...")
  }
}

class sub extends  Base{

  def sayHello(): Unit = {
    this.n1 = 10  //默认权限,ok这里访问本质this.n1_$eq()  -> n1_$eq(10)
    this. n2 = 20 // protected 子类访问ok  -> n2_$eq(20)
    //this.n3 = 30 // private 报错
    println("n1: " + this.n1 + "\tn2: "+ this.n2)
    test1() //默认权限,ok
    test2()  // protected 子类访问ok
    //test3() // private NG 内部和伴生对象中可用
  }

  override def test1(): Unit = {   //需要显式的使用override方法从写
    println("this is sub test1()")
    super.test1()   ////在子类中需要去调用父类的方法,使用super
  }
}

Scala中类型检查和转换  (意义:可以判断传入对象的类型,然后转成对应的子类对象,进行相关操作【多态的特点】)
  1 classOf获取对象的类名
  2 要测试某个对象是否属于某个给定的类,用isInstanceof方法
  3 强转为子类的引用:用asInstanceOf

 classOf[String] 如Java的 String.class 
 obj.isInstanceOf[T] 如Java的obj instanceof T 判断obj是不是T类型
 obj.asInstanceOf[T] 如Java的(T)obj 将obj强转成T类型

 def main(args: Array[String]): Unit = {

    println(classOf[String])  //class java.lang.String //ClassOf的使用,可以得到类名
    var alex = "alex"
    println(alex.getClass.getName) //java.lang.String //使用反射机制

    var aa = new AA
    var bb = new BB
    val cc = new CC
    aa = bb  //将子类引用给父类(向上转型,自动)
    val bb1 = aa.asInstanceOf[BB]   //将父类的引用重新转成子类引用(多态),即向下转型
//    bb1.sayHello()

    tesTypeConvert(cc)   //输出 CC


  }
  //参数多态代码 oop中一个父类的引用可以接收所有子类的引用,多态(参数多态)
  def tesTypeConvert(num: AA) : Unit ={
    if ( num.isInstanceOf[BB]) { //使用Scala中类型检查和转换
      num.asInstanceOf[BB].sayHello()  //num.asInstanceOf[BB],对num的类型没有任何变化,而是返回的是 BB
    }
    else if (num.isInstanceOf[CC]) {
      num.asInstanceOf[CC].sayCC()
    }
    else {println("啥也不是,完犊子艹")}
  }
}

class AA {
  var name: String = "alex"
  def sayHi(): Unit = {
    println("Hi...")
  }
}

class BB extends  AA {
  def sayHello(): Unit = {
    println("hello")
  }
}

class CC extends  AA {
  def sayCC(): Unit= {
    println("CC")
  }
}

超类 

  1.  Java:创建子类对象时,子类的构造器总是去调用一个 父类的构造器(显式或者隐式调用)
  2.  Scala:类有一个主构器和任意数量的辅助构造器,而每个辅助构造器都必须先调用主构造器(也可以是间接调用)
  3.  Scala  只有主构造器可以调用父类的构造器。辅助构造器不能直接调用父类的构造器 (Scala中无 Super 调构造器用法)
object ScalaBaseConstrator {
  def main(args: Array[String]): Unit = {
    //输出AAA父类  1 调用父类主构造器 extends  AAA()
    //BBB 主构造   2 调用本类 主构造器
    //BBB 辅助构造 3 调 本类 辅助构造器
    val bbb = new BBB("alex")

    println("*****************")
    // CCC父类  1 调父类主构造器
    // DDD 主构造 2 调自身主构造器
    val alex_ddd = new DDD("ALEX", 35)
    println("******************")
    // CCC父类  1 调父类主构造器
    // DDD 主构造 2 调自身主构造器
    // DDD 辅助构造器 3 DDD 辅助构造
    val bob_ddd = new DDD("bob")
    println("******************")
    //CCC父类  1 调父类主构造器
    //主构造器默认名字   2 父类辅助构造器
    //EEE 主构造    3 本类主构造器
    //EEE 辅助构造  4 new EEE(参数)先找到 extend CCC => CCC (def this()) => this("默认名字") 主构造器
    val e_EE = new EEE("EEE")
    //CCC父类 1 调父类主构造器
    //主构造器默认名字 2 父类辅助构造器
    //EEE 主构造  3 直接走到了 父类的主构造器
    val e_Empty = new EEE()

  }
}


class AAA (){
  var name: String = _
  println("AAA父类")

}

class  BBB extends  AAA(){
  println("BBB 主构造")
  def this  (name: String) {
    this // 必须调用主构造器
    this.name = name
    println("BBB 辅助构造")
  }
}

class CCC (cName: String){
  var name: String = cName
  println("CCC父类")
  def this() {
    this("默认名字")
    println("主构造器默认名字")
  }
}

class  EEE () extends  CCC(){
  println("EEE 主构造")
  def this  (name: String) {
    this() // 必须调用主构造器
    this.name = name
    println("EEE 辅助构造")
  }
}

class  DDD (dName: String, dInt: Int) extends  CCC(dName){
  println("DDD 主构造")
  def this  (name: String) {
    this(name, 3) // 必须调用主构造器
    this.name = name
    println("DDD 辅助构造")
  }
}
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。