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 }

 

類的繼承和判斷對象是否相等(中)app

 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比較。ide

hashcode相同,equal不必定相同;equal相同的hashcode必定相同。函數

 

類的提取器:(中)this

 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 }

 

 

 類的伴生對象:(高)spa

添加類的內容:scala

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

 

 

這兩種申明是有差的,第二種和第三種申明均可以經過Marker的對象+"."直接調用(至關於這個屬性是靜態的),而第一種申明不行code

1 class Marker private (val color:String) {
2 
3   println("建立" + this)
4   
5   override def toString(): String = "顏色標記:"+ color
6   
7 }

 

private寫在類名和參數中間表示對主構造函數的私有化,這時是不能new出對象的(除非有伴生對象object或者有重構this構造函數)orm

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 }
相關文章
相關標籤/搜索