1. 程式人生 > >Scala入門系列(五):面向對象之類

Scala入門系列(五):面向對象之類

important ica back ember const 就會 out 不用 spa

定義類

// 定義類,包含field以及method class HelloWorld {   private var name = "Leo"   def sayHello() { println("Hello" + name)}   def getName = name } defined class HelloWorld // 創建類對象,並調用其方法 scala> val helloworld = new HelloWorld helloworld: HelloWorld = HelloWorld@4f49f6af  scala> helloworld.sayHello() // 也可以不加括號
HelloLeo scala> print(helloworld.getName) // 不能加括號,因為定義方法的時候沒有加括號 Leo

封裝(setter與getter)

  • 定義不加參數的var filed,Scala會將該字段定義為private,並提供public的getter和setter方法
  • 如果使用private修飾field, 則生成的getter和setter也是private的
  • 如果定義val field, 則只會生成getter方法
  • 如果使用private[this]修飾field,則不會生成getter和setter方法
    總結:Scala提供的四種修飾符:var、val、private、private[this]
class Student {   var name = "sparks" }  defined class Student  scala> val spark = new Student spark: Student = Student@6337c201 // 調用自動生成的setter和getter方法 scala> print(spark.name) sparks  scala> spark.name = "hahah" spark.name: String = hahah 

如果希望能夠自己對getter和setter進行控制,則可以自定義getter與setter方法,使用field和fild_=的方式。

class Student{   private var myName = "Sparks"   def name = "Your name is" + myName   def name_=(newName: String) {     myName = newName   } }  val spark = new Student print(spark.name) spark.name = "Leo" 

註意:自義定setter方法一定要註意scala的語法限制,簽名、_=參數間不能有空格。

private[this]的詳解

如果字段是private修飾的,那麽代碼這個字段時私有的,在類的方法中,可以直接訪問類的其他對象的private field。
例如:

class Student {   private var myAge = 0   def age_=(newValue: Int){     if(newValue>0) { myAge = newValue}     else print("illegal age!")   }   def age = myAge   def older(s: Student) = {     myAge > s.myAge // 調用另一個對象s的私有字段並不報錯   } } 


但是如果是用private[this]修飾,那麽意味著該對象私有字段只有本對象內才可以訪問,上面的代碼就會報錯

<console>:16: error: value myAge is not a member of Student            myAge > s.myAge // 調用另一個對象s的私有字段並不報錯 

Java風格的getter和setter方法

如果要讓scala自動生成java風格的getter和setter方法,只要給field添加@BeanProperty註解即可。
此時會生成4個方法,name: String、 name_=(newValue: String): Unit、 getName(): String、 setName(newValue: String): Unit

// 定義類 import scala.reflect.BeanProperty class Student{   @BeanProperty var name: String = _ }  defined class Student // 測試類 scala> val s = new Student s: Student = Student@5f303ecd scala> s.setName("leo") scala> s.getName() res9: String = leo scala> s.name res10: String = leo scala> s.name = "spark" s.name: String = spark scala> s.getName() res11: String = spark  // 定義Java風格類的第二種方式 class Student(@BeanProperty var name: String) 

構造函數

主構造函數

在Scala中,主constructor是與類名放在一起的,而且類中沒有定義在任何方法或者是代碼塊之中的代碼,就是主constructor的代碼,這點很新穎,但感覺沒有java清晰。

class Student(val name: String, val age: Int) {   println("your name is " + name + ", your age is " + age) }  defined class Student  scala> val s = new Student("spark", 30) your name is spark, your age is 30 s: Student = Student@43b40233  // 還可以使用默認參數 class Student(val name: String = "leo", val age: Int = 30) {    println("your name is " + name + ", your age is " + age) }  defined class Student // 這樣新建對象時就不用傳遞參數了 scala> val s = new Student your name is leo, your age is 30 

註意:如果主constucutor傳入的參數什麽修飾都沒有,比如name: String, 那麽如果類內部的方法使用到了,則會生命為private[this] name; 否則沒有該field,就只能被constructor代碼使用而已。

輔助構造函數(this)

Scala中,可以給類定義多個輔助constructor,類似於java中的構造函數重載
輔助constructor之間可以互相調用,而且必須第一行調用主constructor

// 定義類 class Student{   private var name = ""   private var age = 0   def this(name: String){     this() // 必須調用主構造函數     this.name = name   }   def this(name: String, age:Int) {     this(name) // 必須調用主構造函數     this.age = age   } }  defined class Student // 測試類 scala> val s1 = new Student s1: Student = Student@387bf2d9  scala> val s2 = new Student("sparks") s2: Student = Student@5e746d37  scala> val s3 = new Student("spark", 23) s3: Student = Student@5524b72f 

類部類

在Scala中,同樣可以在類中定義內部類;但是與java不同的是,每個外部類對象的內部類,都是不同的類

// 定義內部類 import scala.collection.mutable.ArrayBuffer class Class{   class Student(val name: String){}   val students = new ArrayBuffer[Student]   def getNewStudent(name: String) = {     new Student(name)   } }  defined class Class  scala> val c1 = new Class scala> val s1 = c1.getNewStudent("spark") scala> c1.students += s1  scala> val c2 = new Class scala> val s2 = c2.getNewStudent("leo") scala> c1.students += s2 // 出錯,因為每個外部類對象的內部類都是不同的類 <console>:15: error: type mismatch;  found   : c2.Student  required: c1.Student               c1.students += s2                              ^

Scala入門系列(五):面向對象之類