Scala的類、屬性、物件欄位

兵工廠三劍客發表於2018-06-12

轉載自:類、屬性、物件欄位

1 類(class)


1.1 定義類

    Scala是一種純粹的物件導向程式語言,而又無縫地結合了命令式和函式式的程式設計風格。在物件導向的語言有兩個重要的概念:類(class)和物件(object也被稱為例項—instance),其中類是物件的抽象。可以把類理解為模板,物件才是真正的實體。

  程式碼示例

[java] view plain copy
  1. class Person() {  
  2.     // 定義age 為類私有屬性  
  3.     private var age = 0//必須初始化欄位  
  4.       
  5.     // 定義方法 age +=1,預設方法公有  
  6.     defincrement(){age += 1}  
  7.   
  8.     // 將age中的值賦值到current  
  9.     def current =age;  
  10. }  
  11.   
  12.   
  13.   
  14.  def main(args:Array[String]): Unit = {  
  15.     val person = new Person();  
  16.     // person.age=10;  //私有的不能設定值  
  17.     person.increment();  
  18.     person.increment();  
  19.     println(person.current);  
  20. }  

  輸出結果:2


1.2 getter/setter方法

  類中的欄位自動帶有getter/setter方法。你也可以用定製的getter/setter方法替換掉原來的欄位的字定義,而不必修改使用的客戶端——這就是所謂的“統一訪問原則”。

  程式碼示例:   

[java] view plain copy
  1.    class Student {  
  2.       // 宣告age屬性,預設生成get\set方法,同時預設age是private  
  3.        var age = 0;  
  4.   
  5.       //私有的變數只有getter方法沒有setter方法  
  6.       // private[this]只能在當前class中使用,不能在其它方法中使用  
  7.       private[this] var privateWeight  = 120;  
  8.   
  9.       // val private[this]修飾的變數只能當前類使用  
  10.       var name = "Scala";   
  11.   
  12.       def weight = privateWeight;  
  13.   
  14.       // 新增 private [this] 關鍵字後只在本類中使用  
  15.       // def isFat(other:Student) = privateWeight < other.privateWeight;  
  16.        }  
  17.   
  18. def main(args: Array[String]): Unit = {  
  19.               val student = new Student();  
  20.              // 賦值時呼叫student.age的set方法   def age_=(x$1: Int): Unit  
  21.              student.age =20  
  22.              // 呼叫student.age,其實上呼叫get方法:def age: Int  
  23.              println(student.age);  
  24. }  

  輸出結果:20


1.3 主建構函式

  Scala中,每個類都有主建構函式,主建構函式並不以this的方式定義,而是與類定義交織在一起,主構造器的引數被編譯成欄位。

  程式碼示例

[java] view plain copy
  1. class Computer /*主建構函式*/() {  
  2.       // 類級別宣告的變數必須賦值  
  3.       var display :String ="LED";  
  4.       // 私有屬性  
  5.       private var price = 3000;  
  6.       // 私有屬性,只能在本類中使用  
  7.       private[this] var cpu = "四核";  
  8.   
  9.       def this(display:String){  
  10.           // 最終都需要呼叫預設this()預設構造  
  11.    this();  
  12.           this.display =display;  
  13.       }  
  14.   
  15.       defsayConfig(){  
  16.           println("顯示器:"+this.display+",價格:"+this.price+",cpu:"+this.cpu);  
  17.       }  
  18. }  
  19.   
  20. def main(args:Array[String]): Unit = {  
  21.       var computer = new Computer();  
  22.       computer.display = "3D";  
  23.       computer  
  24.       computer.sayConfig();  
  25. }  

  輸出結果:顯示器:3D,價格:3000,cpu:四核 


1.4 輔助建構函式

Scala可以有任意多的建構函式,除主建構函式外還有任意多的輔助構造器:

1.輔助類的構造器的名稱為this(如果與類名相同修改類名的時候不方便)

2.每一個輔助構造器都必須以一個對先前已定義的其它輔助或主構造器的呼叫開始。

程式碼示例:          

[java] view plain copy
  1.         class Moblie /*主建構函式*/private /*私有構造器*/(val brand:String,val price:Int){  
  2.               // 定義變數  
  3.               var networkType :String ="";  
  4.               // 過載建構函式  
  5.               def this(brand:String,price:Int,networkType:String){  
  6.                   this(brand,price);  
  7.                   this.networkType =networkType;  
  8.               }  
  9.         }  
  10.           
  11.         def main(args: Array[String]): Unit ={      
  12.         //    // 在建構函式加private修飾,建構函式將不可用  
  13.         //    var moblie = new Moblie("SAMSUNG",4500);  
  14.         //    moblie.networkType = "三星"  
  15.         //       
  16.         //    // 在建構函式加private修飾,建構函式將不可用  
  17.         //    var moblie = new Moblie("SAMSUNG",4500);  
  18.         //    println("品牌:"+moblie.brand);  
  19.         //       
  20.               var moblie = new Moblie("SAMSUNG",4500,"3G網路通訊");  
  21.               println("品牌:"+moblie.brand);  
  22.               println("價格:"+moblie.price);  
  23.               println("通訊型別:"+moblie.networkType);     
  24.         }  


1.5 內部類

   Scala可以將一個類定義在另一個類裡面或者一個方法裡面,這樣的類稱為內部類。

  程式碼示例   

[java] view plain copy
  1.        // class Outer{outer=>語法使得outer變數指向Outer.this。對這個變數,可以 使用任何合法的名稱。  
  2.        class Outer(val name:String){ outer =>  
  3.           class Inner(val name:String){  
  4.               deffoo(b:Inner) = println("Outer:"+outer.name + ",Inner:"+b.name)  
  5.           }  
  6.        }  
  7.       
  8.        def main(args:Array[String]): Unit = {  
  9.           // scala內部類,隸屬於外部類實體本身       
  10.           val outer1 = new Outer("Spark");  
  11.           val outer2 = new Outer("Hadoop");  
  12.       
  13.           val inner1 = new outer1.Inner("scala");  
  14.           val inner2 = new outer2.Inner("java");  
  15.             
  16.           inner1.foo(inner1);  
  17.           inner2.foo(inner2);  
  18.         }  
  輸出結果:

      Outer:SparkInner:scala

      Outer:HadoopInner:java

 

引數生成的欄位及方法:

建構函式

生成的欄位方法

name:String

物件私有欄位。如果沒有方法使用name,則沒有該欄位。

Private

val/var name String

私有欄位,私有getter/setter方法。

Val/var name:String

私有欄位,公有getter/setter方法

 

2 物件(object)


2.1    伴生物件

    在JavaC++中即有例項方法又有靜態方法。在Scala可以通過類與同名的“伴生”物件來達到同樣的目的。

   類和它的伴生物件可以互相訪問私有特性。它們必須在於同一個原始檔中。

   程式碼示例

[java] view plain copy
  1.         // 伴生物件(一般情況下,做為伴生類的靜態區域)  
  2.         object University {  
  3.           private var studentNo = 0;  
  4.           def newStudentNo(): Int = {  
  5.             studentNo = studentNo + 1  
  6.             studentNo  
  7.           }  
  8.         }  
  9.           
  10.         // 伴生類  
  11.         class University {  
  12.           var id = University.studentNo;  
  13.           private var number = 0;  
  14.           def adClass(number: Int) {  
  15.             this.number += number;  
  16.           }  
  17.         }  

2.2    apply方法

    使用apply方法會省去new關鍵字使用起來更方便。通常apply方法返回的是伴生類的類的物件。

[java] view plain copy
  1.     // 伴生類  
  2.         class ApplyTest(){  
  3.             def apply() = println("I am into Spark so much!!!");  
  4.             def haveAtry(){  
  5.             println("Have a try on apply!");  
  6.             }  
  7.         }  
  8.       
  9.         // 伴生物件-apply中的應用  
  10.         object ApplyTest {  
  11.             def apply (): ApplyTest = {   
  12.                 println("I am into Scala to much!!!")  
  13.                 new ApplyTest  
  14.             }  
  15.         }  
  16.         // 方法呼叫  
  17.         object Oop {  
  18.               def main(args: Array[String]): Unit = {  
  19.                   val a = ApplyTest();  
  20.                   a.haveAtry();  
  21.                   println(a());  
  22.               }  
  23.         }  

輸出結果:

      I am into Scala to much!!!

      Have a try on apply!

      I am into Spark so much!!!

   ()


3 物件導向程式設計(OOP)


3.1    scala繼承(extends)

  子類繼承父類的特徵和行為,使得子類具有父類的各種屬性和方法。或子類從父類繼承方法,使得子類具有父類相同的行為。

特點:在繼承關係中,父類更通用、子類更具體。父類具有更一般的特徵和行為,而子類除了具有父類的特徵和行為,還具有一些自己特殊的特徵和行為。在繼承關係中。父類和子類需要滿足is-a的關係。子類是父類。

表示父類和子類的術語:父類和子類、超類和子類、基類和派生類。

  程式碼示例: 

[java] view plain copy
  1.         class Animal(val name:String,val age:Int){  
  2.                println("The primaryconstructor of Animal!!!")  
  3.                // 顏色-白色  
  4.                val color= "white";  
  5.                // 睡覺4小時  
  6.                def sleep = "4hours";  
  7.                // 重寫toString方法  
  8.                override deftoString() = "I am a Animal Animal.toString method";  
  9.            }  
  10.           
  11.            class Dog(name:String,age:Int,val height:String)  
  12.               extends Animal(name,age) {  
  13.               println("This is thesubClass of Animal,Primaryconstructor of Dog!!!")  
  14.                // 重寫color 屬性  
  15.               override val color= "yellow";  
  16.                  
  17.               override deftoString() = "I am a Dog !"super.sleep;     
  18.         }  
  19.           
  20.         //方法呼叫  
  21.           def main(args:Array[String]): Unit = {  
  22.                val dog = new Dog("Poodle",6,"10cm");  
  23.                println(dog.color);  
  24.                println(dog.height);  
  25.                println(dog.toString());  
  26.          }  

輸出結果:

   The primary constructor of Animal!!!

   This is the subClass of Animal,Primary constructor ofDog!!!

   yellow

   10cm

   I am a Dog !4 hours

 

3.2    抽象類(abstractclass)

  使用了關鍵詞abstract宣告的類叫作“抽象類”。如果一個類裡包含了一個或多個抽象方法,類就必須指定成abstract(抽象)。“抽象方法”,屬於一種不完整的方法,只含有一個宣告,沒有方法主體。

     程式碼示例

     

[java] view plain copy
  1.        // 抽象類  
  2.         abstract classSuperTeacher(var name:String){  
  3.             // 定義抽象id 屬性  
  4.             var id : Int;            
  5.             // 定義抽象age 屬性  
  6.             var age: Int;            
  7.             // 定義抽象teach方法  
  8.             def teach;        
  9.         }  
  10.           
  11.           
  12.           
  13.         /* 
  14.         * 實現類TeacherForMaths需要現實抽象類中所有的屬性和方法 
  15.         */  
  16.         classTeacherForMaths(name:String)extends SuperTeacher(name){  
  17.             // 實現 抽象 id 屬性賦值  
  18.             override var id =name.hashCode();            
  19.             // 實現 抽象 age 屬性賦值  
  20.             var age: Int = 25;            
  21.             // 實現 抽象 teach 屬性賦值  
  22.             def teach:Unit = {  
  23.                println("Teaching!!!");            
  24.             }  
  25.         }  
  26.           
  27.           
  28.           
  29.         // 方法呼叫  
  30.          defmain(args: Array[String]): Unit = {  
  31.             var teacher = newTeacherForMaths("Scala");  
  32.             teacher.teach;  
  33.             println("teacher.id="+teacher.id);  
  34.             println("teacher.age="+teacher.age);  
  35.          }  

輸出結果:

      Teaching!!!

      teacher.id=79698214

      teacher.age=25


3.3    特徵(trait)

  特性封裝方法和欄位定義,然後可以通過將它們混合成類被重用。不同於類繼承,其中每個類都必須繼承只有一個父類,一類可以在任意數量特質混合。

  特徵用於通過指定支援的方法的簽名定義的物件型別。Scala中也允許部分實現特性但可能不具有構造引數。trait中可以帶有實現的方法,也可以帶有抽象方法,使用trait的方法是with而混入類中。

  程式碼示例:  

[java] view plain copy
  1.         trait Logger {  
  2.       
  3.            // 空方法,即方法內部不做任務實現  
  4.            deflog(msg:String){}  
  5.         }  
  6.       
  7.        /* 
  8.        * 控制檯日誌類繼承日誌類 
  9.         */  
  10.        class ConsoleLogger extends Logger with Cloneable{  
  11.            defconsoleLogger(){  
  12.               println("It'sme !!!");     
  13.            }  
  14.        }  
  15.       
  16.        /* 
  17.         * 使用trait關鍵字混入日誌 
  18.        */  
  19.        trait TraitLogger extends Logger {  
  20.            override def log(msg:String){  
  21.               println("TraitLoggerlog is :" + msg);  
  22.            }  
  23.        }  
  24.       
  25.        // 程式碼呼叫  
  26.       def main(args:Array[String]): Unit = {  
  27.             // 子類重寫父類的方法  
  28.             var consoleLogger = newConsoleLogger();  
  29.             consoleLogger.consoleLogger();  
  30.       
  31.             // trait關鍵字混入  
  32.             val traitlogger = newConsoleLogger with TraitLogger  
  33.             traitlogger.log("It'sme !!!")  
  34.       }  

輸出結果:

      It's me !!!

      TraitLogger log is :It's me !!!


3.4    多重繼承

   Scala的類只能夠繼承單一父類,但是如果是特徵的話就可以繼承多個,從結果來看就是實現了多重繼承。  

        程式碼示例

[java] view plain copy
  1. // 定義Human類  
  2. class Human(){  
  3.     println("Human");  
  4. }  
  5.   
  6. // 定義trait特性,繼承Human類  
  7. trait TTeacher extends Human(){  
  8.     println("TTeacher");  
  9.   
  10.     // 抽象方法  
  11.     def teach  
  12. }     
  13.   
  14.   
  15. // 定義trait PianoPlayer繼承Human  
  16. trait PianoPlayer extends Human(){  
  17.    println("PianoPlayer");  
  18.    defpianoPlayer = {println("I'm playing piano.")}  
  19. }  
  20.   
  21. // PianoTeacher類,繼承Human類,實現TTeacher特徵、PianoPlayer特徵。  
  22. // 物件在構造時,依次從左向右構造  
  23. class PianoTeacher() extends Human with TTeacher withPianoPlayer {  
  24.     // 實現TTeacher中teach方法  
  25.     override def teach ={println("I'm training students.")}  
  26. }  



3.5    AOP實現

AOPAspect Oriented Programming的縮寫,意為:面向切面程式設計,通過預編譯方式和執行期動態代理實現程式功能的統一維護的一種技術。AOPOOP的延續,是軟體開發中的一個熱點,是函數語言程式設計的一種衍生範型。利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程式的可重用性,同時提高了開發的效率。

  程式碼示例

[java] view plain copy
  1.       // 定義特徵Action  
  2.        trait Action {  
  3.            def doAction  
  4.        }  
  5.       
  6.        // 被加入的方面,定義一下加入了前置處理和後置處理的特徵TBeforeAfter  
  7.        trait TBeforeAfter extends Action {  
  8.            // abstractoverride 關鍵字覆蓋預設抽象方法,  
  9.            // 實際被執行的是被呼叫的實體類中所定義的方法,實際執行將由子類實現。  
  10.            abstract override def doAction{  
  11.               // 呼叫super.doAction之前的列印  
  12.               println("Initialization");  
  13.               // 呼叫super.doAction方法  
  14.               super.doAction  
  15.               // 呼叫super.doAction之後的列印  
  16.               println("Destroyed");  
  17.            }  
  18.        }  
  19.       
  20.        // Work類實現Action特徵  
  21.        class Work extends Action {  
  22.            // 實現doAction方法  
  23.            override def doAction= println("Working...")  
  24.          }   
  25.       
  26.         // 程式碼呼叫  
  27.         def main(args:Array[String]): Unit = {  
  28.             // 呼叫doAction方法  
  29.              val work = new Work withTBeforeAfter;  
  30.              work.doAction;     
  31.         }  

輸出結果:

      Initialization

      Working...

      Destroyed

相關文章