官术网_书友最值得收藏!

1.5 類和對象

1.5.1 類的定義

我們已經知道,對象是類的具體實例,類是抽象的,不占用內存,而對象是具體的,占用存儲空間。

Scala中一個簡單的類定義是使用關鍵字class,類名必須大寫。類中的方法用關鍵字def定義,例如以下代碼:

如果一個類不寫訪問修飾符,那么默認訪問級別為Public,這與Java是不一樣的。

關鍵字new用于創建類的實例。例如,調用上述代碼中的count()方法,可以使用以下代碼:

new User().count()

1.5.2 單例對象

Scala中沒有靜態方法或靜態字段,但是可以使用關鍵字object定義一個單例對象,單例對象中的方法相當于Java中的靜態方法,可以直接使用“單例對象名.方法名”方式進行調用。單例對象除了沒有構造器參數外,可以擁有類的所有特性。

例如以下代碼定義了一個單例對象Person,該對象中定義了一個方法showInfo():

可以在任何類或對象中使用代碼Person.showInfo()對方法showInfo()進行調用。

1.5.3 伴生對象

當單例對象的名稱與某個類的名稱一樣時,該對象被稱為這個類的伴生對象。類被稱為該對象的伴生類。

類和它的伴生對象必須定義在同一個文件中,且兩者可以互相訪問其私有成員。例如以下代碼:

運行上述伴生對象Person的main方法,輸出結果如下:

姓名:zhangsan
年齡:20

1.5.4 get和set方法

Scala默認會根據類的屬性的修飾符生成不同的get和set方法,生成原則如下:

? val修飾的屬性,系統會自動生成一個私有常量屬性和一個公有get方法。

? var修飾的屬性,系統會自動生成一個私有變量和一對公有get/set方法。

? private var修飾的屬性,系統會自動生成一對私有get/set方法,相當于類的私有屬性,只能在類的內部和伴生對象中使用。

? private[this]修飾的屬性,系統不會生成get/set方法,即只能在類的內部使用該屬性。

例如有一個Person類,代碼如下:

class Person {
  val id:Int=10
  var name="zhangsan"
  private var gender:Int=0
  private[this] var age:Int=20
}

將該類編譯為class文件后,再使用Java反編譯工具將其反編譯為Java代碼,代碼如下:

使用name屬性舉例,在Scala中,get和set方法并非被命名為getName和setName,而是被命名為name和name_=,由于JVM不允許在方法名中出現=,因此=被翻譯成$eq。

從上述代碼可以看出,由于屬性id使用val修飾,因此不可修改,只生成了與get方法對應的id();屬性name使用var修飾,因此生成了與get和set方法對應的name()和name_$eq()方法,且都為public;屬性gender由于使用private var修飾,因此生成了private修飾的get和set方法;屬性age由于使用private[this]修飾,因此沒有生成get和set方法,只能在類的內部使用。

此時可以使用如下代碼對Person類中的屬性進行訪問:

除了系統自動生成get和set方法外,也可以手動進行編寫,例如以下代碼:

當然也可以使用如下Java風格定義get和set方法:

1.5.5 構造器

Scala中的構造器分為主構造器和輔助構造器。

1.主構造器

主構造器的參數直接放在類名之后,且將被編譯為類的成員變量,其值在初始化類時傳入。例如以下代碼:

可以通過對主構造器的參數添加訪問修飾符來控制參數的訪問權限。例如以下代碼,將參數age設置為私有的,參數name設置為不可修改(val):

class Person(val name:String, private var age:Int) {
}

構造參數也可以不帶val或var,此時默認為private[this] val,代碼如下:

class Person(name:String,age:Int) {
}

在主構造器被執行時,類定義中的所有語句同樣會被執行。例如以下代碼中的println語句是主構造器的一部分,每當主構造器被執行時,該部分代碼同樣會被執行,可以在這里做一些類的初始化工作:

class Person(var name:String,var age:Int) {
  println(name)
  println(age)
  //初始化語句...
}

如果需要將整個主構造器設置為私有的,那么只需要添加private關鍵字即可,例如以下代碼:

class Person private(var name:String,var age:Int) {
}

注意,主構造器也可以沒有參數,一個類中如果沒有顯式地定義主構造器,就默認有一個無參構造器。

2.輔助構造器

Scala類除了可以有主構造器外,還可以有任意多個輔助構造器。輔助構造器的定義需要注意以下幾點:

? 輔助構造器的方法名稱為this。

? 每一個輔助構造器的方法體中必須首先調用其他已定義的構造器。

? 輔助構造器的參數不能使用var或val進行修飾。

例如以下代碼定義了兩個輔助構造器:

上述構造器可以使用如下3種方式進行調用:

var per1=new Person                  //調用無參主構造器
var per2=new Person("lisi")          //調用輔助構造器一
var per3=new Person("lisi",28) //調用輔助構造器二

除此之外,主構造器還可以與輔助構造器同時使用,在這種情況下,一般輔助構造器的參數要多于主構造器,代碼如下:

上述代碼運行的輸出結果為:

zhangsan
20
male
主站蜘蛛池模板: 宁远县| 周口市| 滁州市| 油尖旺区| 新宁县| 金川县| 湘潭市| 天门市| 安吉县| 菏泽市| 浦县| 渝北区| 阆中市| 安陆市| 阿拉善盟| 兴和县| 黔西| 新巴尔虎左旗| 桐庐县| 彰化市| 长顺县| 城固县| 澄江县| 余江县| 商南县| 星子县| 县级市| 中宁县| 余庆县| 衡山县| 类乌齐县| 浦东新区| 双流县| 平罗县| 绥宁县| 余江县| 全南县| 滁州市| 禹城市| 富宁县| 甘南县|