• Scala学习——类,继承,接口(中)


    基本类的使用:(初)

     1 package com.dtspark.scala.basics
     2 /**
     3  * trait是一个接口
     4  * 接口的第一次继承用extends,多继承时用with
     5  * 多继承时,如果这些接口中都有同样的方法时,则是从右往左的顺序执行
     6  * 抽象类不能实例化
     7  * 类继承的时候不继承伴生对象object,只能看见类的接口,而其父类可以使用自己伴生对象中的方法
     8  * isInstanceOf 和 asInstanceOf的使用
     9  * 前者是判断是不是其子类,后者是进行类型转换,但必须是父子之间的转换,不能是完全不同的类
    10  */
    11 trait Logger{
    12   def log(message:String){
    13     println("logger "+message)
    14   }
    15   
    16 }
    17 /**
    18  * override 是表示重写原有方法,(必须要写)
    19  */
    20 trait RichLogger extends Logger{
    21   override def log(message:String){
    22     println("RichLogger:"+message)
    23   }
    24 }
    25 
    26 class Loggin( name:String)extends Logger{
    27   def loggin{
    28     println("Hi,welcome! "+name)
    29     log(name)
    30   }
    31 
    32 }
    33 
    34 
    35 
    36 trait Information{
    37   
    38   val information:String //抽象属性
    39   //def getId:String
    40   def getInformation:String //抽象方法(不存在方法体)
    41   def checkIn:Boolean = {
    42     getInformation.equals("Spark")
    43   }
    44 }
    45 
    46 class Passenger( name:String)extends Information{
    47   //不可以定义为val 原因是因为_的值不明确
    48   var id:String=_ //这种方法申明的不是抽象属性,而是可变属性,其值为String的默认值null
    49   override val information = name //重写抽象属性
    50   override def getInformation = information //不执行任何操作,直接给返回值,相当于实现了
    51   /**
    52    * this关键字为构造方法,重写构造方法
    53    * 副构造函数的第一行必须是构造函数
    54    */
    55   def this(name:String,iid:String){
    56     this(name)
    57     id=iid;
    58     println("hello!!")
    59   }
    60   def out:String={
    61     name+" : "+id
    62   }
    63   
    64 }
    65 
    66 object HelloTrait {
    67   def main(args: Array[String]): Unit = {
    68     /**
    69      * 对象实例化之后又继承了新的接口,可以使用新的方法
    70      * 新的接口必须继承至原有的接口,并重写新的方法
    71      */
    72     val Log = new Loggin("Spark")with RichLogger
    73     Log.loggin
    74     
    75     val person = new Passenger("zcb")
    76     println(person.out)
    77     person.id="123"  //不具有封装性
    78     println(person.out)
    79     val person1 = new Passenger("zcb1","1234")
    80     println(person1.out)
    81     val a:Boolean=person.isInstanceOf[Information]//看它是不是其子类
    82     println(a)
    83   }
    84 }

    类的继承和判断对象是否相等(中)

     1 package com.dtspark.scala.basics
     2 /**
     3  *class Creature {
     4  *   val range: Int = 10
     5  *   val env: Array[Int] = new Array[Int](range)
     6  *}
     7   
     8  *class Ant extends Creature {
     9  *   override val range = 2
    10  *}
    11  * 在构造时,发生的过程如下:
    12  * Ant构造器在构造自己之前,调用超类构造器;
    13  * Creature的构造器将range字段设为10;
    14  * Creature的构造器初始化env数组,调用range字段的getter;
    15  * range的getter被Ant类重写了,返回的Ant类中的range,但是Ant类还未初始化,所以返回了0;
    16  * env被设置成长度为0的数组
    17  * Ant构造器继续执行,将range字段设为2
    18  * -------------------------------------------------------------
    19  * 第二种写法是先初始化sporter的成员,然后在初始化父类的成员,这样可保证将数据传给父类,with后面接要继承的类
    20  * class Person10{
    21  *  val counter=3
    22  *  val counterArray =new Array[Int](counter)
    23  * }
    24  
    25  * class Sporter extends {
    26  *   override val counter = 5
    27  * }with Person10
    28       
    29 **/这样初始化后sporter的counterArray的长度为5
    30 class Person10{
    31   val counter=3
    32   val counterArray =new Array[Int](counter)
    33 }
    34 
    35 class Sporter extends {
    36   override val counter = 5
    37 }with Person10
    38 
    39 //判断两个对象是否相同的方法
    40 class Programmer(val name:String,val salary:Double){
    41   final override def equals(other:Any)={
    42     val that = other.asInstanceOf[Programmer]
    43     if(that==null)false
    44     else name == that.name&&salary==that.salary
    45   }
    46   /**
    47    * 1.hashCode()方法存在的主要目的就是提高效率。
    48      * 2.在集合中判断两个对象相等的条件,其实无论是往集合中存数据,
    49      * 还是从集合中取数据,包括如果控制唯一性等,都是用这个条件判断的,条件如下:
    50    * 首先判断两个对象的hashCode是否相等,如果不相等,就认为这两个对象不相等,就完成了。
    51    * 如果相等,才会判断两个对象的equals()是否相等,如果不相等,就认为这两个对象不相等,
    52    * 如果相等,那就认为这两个对象相等。
    53                
    54    * 所以说重写equals时必须重写hashcode,这是良好的习惯
    55    */
    56   final override def hashCode=name.hashCode()*5+salary.hashCode()*9
    57   
    58 }
    59 
    60 //object OverrideField {
    61 //  def main(args: Array[String]): Unit = {
    62 //    val s = new Sporter
    63 //    println(s.counterArray.length)
    64 //  }
    65 //}
    66 //第二种写法,不用写main函数
    67 object OverrideField extends App{
    68     val s = new Sporter
    69     println(s.counterArray.length)
    70 }

     注:对于无序表寻找是否有相同的对象时,使用hashcode可以大大提高速度。equal的比较通常比较耗资源,可以先比较hashcode后,确认hashcode相同时再用equal比较。

    hashcode相同,equal不一定相同;equal相同的hashcode一定相同。

    类的提取器:(中)

     1 package com.dtspark.scala.basics
     2 /**
     3  * 类的提取器
     4  * 注解要搞懂下面两个
     5  * @transient 注解将字段标记为瞬态的
     6  * @volatile 注解标记为易失的
     7  *
     8  * 自己编写的注解要继承annotation.Annotation
     9  */
    10 case class Person1(name:String ,age:Int)
    11  
    12 class DTCoder(val name:String ,val salary:Int)
    13 object DTCoder{
    14   //复写了其apply和unapply方法
    15   def apply(name:String,salary:Int)={
    16     println("DTCoder apply method invoked!!!")
    17     new DTCoder(name,salary)
    18   }
    19 //  方法1 (可使一个字符串转换成一个对象)
    20 //  def unapply(information:String)={
    21 //    //根据空格区分参数
    22 //    println("DTCoder unapply method invoked!!!")
    23 //    Some((information.substring(0 , information.indexOf(" ")),information.substring(information.indexOf(" ")+1)))
    24 //  }
    25 //方法二
    26   def unapply(information:DTCoder)={
    27     //根据空格区分参数
    28     println("DTCoder unapply method invoked!!!")
    29     Some((information.name,information.salary))
    30   }
    31 }
    32  
    33 object HelloExtractor {
    34   def main(args: Array[String]): Unit = {
    35     val person=Person1("Spark",12)//调用apply的工厂构造方法,构造出类的实例
    36     //= val person =Person1.apply("Spark",12)
    37     val Person1(name,age)=person//调用Person1的unapply的方法把person实例中的name和age提取出来
    38     println(person.name+" : "+person.age)//实现了name和age的赋值。
    39      
    40     person match{ //val Person1(name,age)=person=match这个过程
    41       case Person1(name,age)=>println(name+" : "+age)
    42     }
    43     //针对unapply方法一
    44     //val DTCoder(dtname,salary) = "Spark 16000000"
    45      
    46     //针对unapply方法二
    47     val coder = DTCoder("Spark",2999999)
    48     val DTCoder(dtname,salary)=coder
    49   }
    50 }

     类的伴生对象:(高)

    添加类的内容:

    1 class Marker ( color:String)
    2 class Marker (val color:String)
    3 class Marker (var color:String)
     

    这两种申明是有差的,第二种和第三种申明都可以通过Marker的对象+"."直接调用(相当于这个属性是静态的),而第一种申明不行

    1 class Marker private (val color:String) {
    2 
    3   println("创建" + this)
    4   
    5   override def toString(): String = "颜色标记:"+ color
    6   
    7 }

    private写在类名和参数中间表示对主构造函数的私有化,这时是不能new出对象的(除非有伴生对象object或者有重构this构造函数)

    1 def main(args: Array[String]) { 
    2        new Marker("black")//报错
    3 }
    第一种解决方案:
    添加object后,同时要有apply方法,否则还是报错(伴生对象是不带参数的,但是apply方法需要与原类相同的参数)
    由于有apply方法的存在,创建新对象时,不需要用new关键字,
    用object初始化时,他会直接初始化object中存在的所有变量。
     1 object zcb01 {
     2     def main(args: Array[String]) { 
     3          Marker("white") //直接对象名进行初始化
     4     }
     5 
     6 }
     7  class Marker (val color:String) {
     8 
     9   println("创建" + this)
    10   
    11   override def toString(): String = "颜色标记:"+ color
    12   
    13 }
    14 
    15 
    16 object Marker{
    17   
    18     private val markers: Map[String, Marker] = Map(
    19       "red" -> new Marker("red"),
    20       "blue" -> new Marker("blue"),
    21       "green" -> new Marker("green")
    22     )
    23     private val m = Set(new Marker("black"))
    24     def apply(color:String) = {
    25       if(markers.contains(color)) markers(color) else null
    26       println("我输入的颜色:"+color)
    27     }
    28 
    29 }

    结果:(先将object中的元素初始化,然后再调用apply方法初始化当前对象)

    创建颜色标记:red
    创建颜色标记:blue
    创建颜色标记:green
    创建颜色标记:black
    我输入的颜色:white

     

    第二种解决方案:
    重构构造器(创建对象时必须用new,因为object(apply方法)不支持除主构造以外的任何重载构造方式)
     1 object zcb01 {
     2     def main(args: Array[String]) { 
     3           new Marker("white",4)
     4     }
     5 
     6 }
     7  class Marker private (val color:String) {//主构造的形式与类名后面的形式相同
     8 
     9   println("创建" + this)
    10   var a=1;
    11 
    12   def this(color:String,a:Int){
    13     this(color)//必须先调用主构造器
    14     this.a=a;
    15   }
    16   
    17   override def toString(): String = "颜色标记:"+ color
    18   
    19 }
  • 相关阅读:
    7. 输油管道问题
    6. 循环赛日程表
    4.JSP内置对象
    3.JSP
    2.CSS
    1.HTML
    5. 逆序对数
    [转]Android View.onMeasure方法的理解
    [转]android:clipToPadding和android:clipChildren
    [转]倍数提高工作效率的 Android Studio 奇技
  • 原文地址:https://www.cnblogs.com/LazyJoJo/p/6410392.html
Copyright © 2020-2023  润新知