• scala -- 继承


    继承

    抽象类 abstract 为修饰符的类 是不能被实例化的

    抽象方法 没有实现的方法— 方法没有= 或者是没有 方法体

    ​ 具有抽象方法的类,必须被声明为抽象类。

    abstract class Element { // abstract 关键字表示这是一个抽象类
      def contents: Array[String]  // 该方法为抽象方法,
      def height:Int = contents.length 
      def Int = if (height == 0 ) 0 else contents.length
    }
    
    无参数方法 空括号方法
    def width():Int  //空括号方法 没有参数
    def widht:Int  //无参数方法
    

    ​ 空括号方法和无参数方法是可以互相重写的。也可以在调用没有任何参数的方法的时候,省略空括号。原则上,scala 函数调用中可以省略所有的空括号,但是推荐是:调用方法超出其对象属性时,建议保留空括号。如果该方法带有副作用那么也不要省略空括号。因为那会看起来像是在使用字段。另一方面想是:如果你的函数执行了操作,那就带有空括号,如果方法只是提供了对某些属性的访问,那就不要带空括号。

    统一访问原则

    ​ 统一访问原则:只要方法中没有参数并且方法仅能通过读取所包含对象的属性去访问可变状态(也就是说,只能读不能修改可变状态)就是用无参数方法,也就是说,客户代码不应由属性是通过字段实现还是方法实现而受到影响。

     def height:Int = contents.length 
     val height:Int = contents.length  //这两个结果是一样的
    

    上面二者结果是一样的,他们的区别:是字段需要分配内存,访问字段比较快,而方法每次调用时都要计算,因此比较慢。单不需要内存空间。

    扩展类(继承)

    extends 修饰符,关键字 表示 扩展/继承

    class ArrayElement(conts:Array[String]) extends Element{
      def contents:Array[String] = conts
    }
    

    继承 重写 实现
    ​ extends 使 ArrayElemen 继承了 抽象类 Element 的所有非私有成员。ArrayElement 是 Element的子类。Element 是ArrayElement的超类。如果没有指明extends扩展的是哪一类,那么默认的超类是scala.AnyRef 与java的javal.lang.Object 类似。
    ​ 继承:1 所有的超类成员除了私有的,也是子类的。2.超类和子类中出现了同名的成员名称或者参数,那么子类不会继承超类的该方法,这种情况叫 重写(override)。
    ​ 如果想上例 contents 方法一样,子类中是具体的,超类中是抽象的,那么叫子类实现了超类的成员。其实意思一样,只是叫法不同而已。

    自类型化
    val e:Element = new ArrayElement(Array("HELLO"))
    

    ​ 子类型化。 子类的值可以在任何需要其超类值的地方使用。 这种现象叫做 多态。即 父类对象,可以有很多形式(具体的多个子类对象)
    ​ 变量 e 被定义为Element 类型,所以其初始化值也应该是 Element,但是实际上初始化的是ArrayElement类型对象。这样写是因为,ArrayElement 扩展了Element,所以,ArrayElement兼容Element

    命名空间

    java有四个命名空间:字段、方法、类型、包,所以他们的字段名可以和方法名一样。

    scala只有两个命名空间:
    ​ 1、值(字段、方法、包、单例对象) 2、类型(类名和特质名)

    ​ 所以,1.scala中方法名和字段名是不能相同的。

    ​ 2. 字段可以重写无参数方法

    class ArrayElement(conts:Array[String]) extends Element{
       val contents:Array[String] = conts //字段重写了方法	统一访问原则
    }
    
    参数化字段
    class ArrayElement(val contents:Array[String]) extends Element{ } 
    

    ​ 参数前面加了一个 val 前缀。这是同时定义同名参数和字段的一个简写形式。其实际就是上面那中写法。现在ArrayElemt类拥有了一个val 字段 contents 只可以在访问,不可以修改。
    ​ 同样的类参数也可以使用 var 做前缀。 如class Cat(var name){},这些参数化字段也可以添加private project override 等前缀,就好像在类内部进行操作一样.scala会根据类参数创造相应的包含类参数的 主构造器。

    class Cat(val dangerous:Boolean = false)
    class Tiger(
               override val dangerous:Boolean = true,
               private var age:Int
               )extends  Cat
    

    上面这种方法,是下面方法的简写

    class Cat(ant:Boolean){
      val dangerous:Boolean = ant
    }
    class Tiger(dae:Boolean,ages:Int) extends Cat(dae){ //调用超类的主构造器,dae 会是会主构造的参数。
      override val dangerous:Boolean = dae // scala 规定,如果子类成员重写了父类成员,那么必须写 override修饰符,而子类实现抽象类成员,则可以选写。如果子类没有重写超类的成员,则禁止写override修饰符
      private var age:Int = ages
    }
    
    
    动态绑定
    object ClassSt{
      abstract class Animal{ //抽象类
        def song:String //抽象成员 具体说是 抽象方法
        def drink:String = "water" //非抽象方法,
      }
    
      class Duck(val voice:String)extends Animal{ // 实现抽象类
        override def song: String = voice  //实现抽象方法
      }
      class Chicken(val voice:String) extends Animal{
        override def song: String = voice
      }
      class Dog(val voice:String) extends Animal{
        override def song: String = voice
      }
    
      def main(args: Array[String]): Unit = {
        val duck:Animal = new Duck("gaga")  //子类型化 同时也体现了动态绑定。
        val chicken:Animal = new Chicken("jiji")//虽然chicken声明是Animal 类型,但是运行时方法调用是基于 chicken 是Chicken 类的实例
        val dog:Animal = new Dog("wof")
        println(duck.song) //gaga
        println(chicken.song)//jiji
        println(dog.song)//wof
        println(dog.drink) //water  继承了超类的drink 方法。因为在Dog类中,并没有重写该方法,所以调用了超类的该方法。
      }
    }
    

    动态绑定

    被动用的实际方法实现,取决于运行期间,对象基于的类(对象是哪个类的实例),而不是取决于变量或表达式的类型。

    禁止重写 禁止继承

    final 修饰 字段、方法表示 禁止重写

    ​ 修饰类表示禁止 继承

    abstract class Animal{
        def song:String
        final def drink:String = "water"
        var name = "animal"
        val age = 10
        final var hisSon  = "little animal"
        final val hisBrother = "older animal"
      }
    
      class Duck(val voice:String)extends Animal{
        override def song: String = voice //重写了超类的song方法
        name = "duck" //超类定义一个var name表明name是可以修改的,Duck会继承这个变量,然后重新赋值
    //  age = 100 // age 是超类中 是val 不可变的,所以这么写会报错,如果想要修改val 的值,那么只能重写
        override val age: Int = 100 // 重写超类的 val age 变量
        hisSon = "little duck" //hison 是一个var 变量,虽然定义了final 但是这里并没有重写,而是重新赋值,所以,final对与var 成员是没什么用的
    //    override hisBrother = "older duck" //hisBrother 是val 的,所以如果需要重新赋值,只能通过重写的方式,但是超类中hisBrother 有final修饰符,严禁重写,所以 这么写会报错的。
    
      }
    
      //abstract  final class Animal{ //final 写在哪里都行只要在 "class" 前面即可
      final abstract class Animal{
        def song:String
      }
    
      class Duck(val voice:String)extends Animal{ //会报错
        override def song: String = voice
      }
    
    
  • 相关阅读:
    [HNOI2006] 公路修建问题
    [8.16模拟赛] 玩具 (dp/字符串)
    [NOI2014] 动物园
    [CF816E] Karen and Supermarket1 [树形dp]
    [POI2006] OKR-period of words
    [BZOJ4260] Codechef REBXOR
    [POJ3630] Phone List
    正确答案 [Hash/枚举]
    The xor-longest Path [Trie]
    [NOI1999] 生日蛋糕
  • 原文地址:https://www.cnblogs.com/jijizhazha/p/7224489.html
Copyright © 2020-2023  润新知