1. 程式人生 > >【圖文詳細 】Scala——類

【圖文詳細 】Scala——類

1、Scala 類 

Scala 的類與 Java、C++的類比起來更簡潔,學完之後你會更愛 Scala!!! 

 

1.1、定義類 
定義一個 Student 類: 

package com.mazh.scala.day2.oop 
  
// 在 Scala
中,類並不用宣告為 public 。 
// 在 Scala
檔案中,檔名可以不用和類名一致 
//Scala
原始檔中可以包含多個類,所有這些類都具有公有可見性 
class Person { 
 
  // 用 val
修飾的變數是隻讀屬性,有 getter
但沒有 setter 
  // (相當與 Java
中用 final
修飾的變數) 
  val id = "100" 
 /** 
 * 作者: 李濤: https://blog.csdn.net/qq_42246689
 */ 
  // 用 var
修飾的變數既有 getter
又有 setter 
  var age: Int = 33 
 
  // 類私有欄位 , 只能在 當前 類的內部或伴生物件中使用   private var name: String = "黃渤" 
 
  // 物件私有欄位 , 訪問許可權更加嚴格的, Person
類的方法只能訪問到當前物件的欄位 
// 伴生物件都不能訪問   private[this] val nickname = "影帝" 
}

通過反編譯工具反編譯之後看到: 

package com.mazh.scala.util; 
 
public class Person { 
   private final String id = "100"; 
   private int age = 33;
    private String name = "黃渤";
    private final String nickname = "影帝"; 
    
   // 相當於 id屬性的 getId() 方法 
   public String id() { 
      return this.id; 
   } 
    
   // 相當與 age屬性的 getAge() 方法 
 public int age() { 
      return this.age; 
   } 
    
   // 相當與 age屬性的 setAge方法 
   public void age_$eq(int x$1) { 
      this.age = x$1; 
   } 
    
   // name屬性的私有 get方法 
   private String name() { 
      return this.name; 
   } 
    
   // name屬性的私有 set方法 
   private void name_$eq(String x$1) { 
      this.name = x$1; 
   } 
} 

通過 JDK 自帶的反編譯工具反編譯: 

C:\IdeaProjects-2017-02-07\ScalaTest\out\production\ScalaTest\com\mazh\scala\day2\oop>java p -private Person
 警告: 二進位制檔案 Person 包含
 com.mazh.scala.day2.oop.Person
 Compiled from "Person.scala"
 public class com.mazh.scala.day2.oop.Person {
   private final java.lang.String id;
   private int age;
   private java.lang.String name;
   private final java.lang.String nickname;
   public java.lang.String id();
   public int age();
   public void age_$eq(int);
   private java.lang.String name();
   private void name_$eq(java.lang.String);
   public com.mazh.scala.day2.oop.Person();
 } 

下面這張圖給出了 setter 和 getter 方法的生成關係: 

 

1.2、定義構造器 
注意:主構造器會執行類定義中的所有語句 
 
定義一個 Student 類:

package com.mazh.scala.day2.oop 
 
import java.io.IOException 
 
/** 
  * 每個類都有主構造器,主構造器的引數直接放置類名後面,與類交織在一起 * 主構造器會執行類定義中的所有語句 
* 當在創 建物件時,需要進行相關初始化操作時,可以將初始化語句放在類體中 
* 同樣也可以在類中新增或重寫相關方法 
  */ 
class Student(val name: String, val age: Int){
   println("執行主構造器") 
 
  try {
     println("讀取檔案") 
    throw new IOException("io exception") 
  } catch {
     case e: NullPointerException => println("列印異常 Exception : " + e)
     case e: IOException => println("列印異常 Exception : " + e) 
  } finally {
     println("執行 finally 部分") 
  } 
 
  private var gender = "male" 
 
  // 用 this關鍵字定義輔助構造器 
  def this(name: String, age: Int, gender: String){ 
    // 每個輔助構造器必須以主構造器或其他的輔助構造器的呼叫開始
     this(name, age)
     println("執行輔助構造器") 
    this.gender = gender 
  } 
} 

定義輔助構造器:

如果禁用掉了主構建器(使用 private 宣告),則必須使用輔助建構函式來建立物件。 
 
輔助建構函式具有兩個特點:

1、輔助構建器的名稱為 this,Java 中的輔助建構函式與類名相同,這常常會導致修改類名 時出現不少問題,scala 語言避免了這樣的問題;

2、呼叫輔助建構函式時,必須先呼叫主建構函式或其它已經定義好的建構函式。 
 
定義一個 Queen 類: 

package com.mazh.scala.day2.oop 
 
// 構造器引數可以不帶 val或 var , 
// 如果不帶 val或 var的引數至少被一個方法所使用 , 那麼它將會被提升為欄位 
// 在類名後面加 private就變成了私有的 ,相當於 禁用了主構造器 
class Queen private(val name: String, prop: Array[String], private var age: Int = 18){ 
   
  println(prop.size) 
 
  //prop被下面的方法使用後, prop就變成了不可變的 物件私有欄位, 
// 等同於 private[this] val prop 
  // 如果沒有被方法使用該引數將不被儲存為欄位 
// 僅僅是一個可以被主構造器中的程式碼訪問的普通引數
   def description = name + " is " + age + " years old with " + prop.toBuffer 
} 
 
object Queen{ 
 def main(args: Array[String]) { 
    // 私有的構造器,只有在其伴生物件中使用
     val q = new Queen("劉亦菲", Array("女神", "女神經"), 20) 
    println(q.description()) 
  } 
}

總結: 主構造方法:

1、與類名交織在一起

2、主構造方法執行,導致類名後面的大括號裡面的程式碼都會執行

輔助構造方法:

1、名字必須叫 this

2、必須以呼叫主構造方法或者是其他輔助構造方法開始

3、裡面的屬性不能寫修飾符