快學scala 第五章 讀書筆記及習題答案程式碼
chapter 5 類
標籤:快學scala
一、筆記
- scala類方法預設是公有的,
classCounter{
private val value =0
def increment(){ value +=1}
def current()= value
}
val = myCounter =newCounter//或new Counter()
myCounter.current //ok
println(myCounter.current)
對於改值器方法使用(),對於取值器則去掉()。
2. java中getter和setter方法比公有欄位更好。scala生成面向JVM的類。實現屬性時有四個選擇:
a. var foo:Scala自動合成一個getter和一個setter.
b. var foo:Scala自動合成一個getter
c. 由你來定義foo和foo_=方法
d. 由你來定義foo方法
所以scala中不能只寫屬性(只帶有settter沒有gettter的屬性)。
3. 輔助構造器的名稱為this,每個輔助構造器都必須以一個對先前已定義的其他輔助構造器或主構造器呼叫開始。
classPerson{
privatevar name =""
private vat age =0
defthis(name:String){//輔助構造器
this()//呼叫主構造器
this.name = name
}
defthis(name:String, age:Int){//另一個輔助...
this(name)//呼叫前一個輔助構造器
this.age = age
}
}
class Persion(val name: String, val age: Int){
...
}
主構造器被編譯成欄位,其值被初始化為構造時傳入的引數。
classPersion(val name:String, val age
println("Just constructed another person")
def description = name +" is "+ age +" years old"
}
二、習題答案
5.1 改進5.1節的Counter類,讓它不要在Int.MaxValue時變成負數
classCount{
privatevar value =0
def increment(){if(value <Int.MaxValue) value +1else value }
def current = value
}
5.2 編寫一個BankAccount類,加入deposit和withdraw方法,和一個只讀的balance屬性
classBankCount(val balance:Int=0){
def deposit(){}
def withdraw(){}
}
5.3 編寫一個Time類,加入只讀屬性hours和minutes,和一個檢查某一時刻是否早於另一時刻的方法before(other:Time):Boolean。Time物件應該以new Time(hrs,min)方式構建。其中hrs以軍用時間格式呈現(介於0和23之間)
classTime(private[this] val hrs:Int,private[this] val min:Int){
val hours = hrs
val minutes = min
def before(other:Time):Boolean={
if(hours < other.hours)
true
if(hours == other.hours)
if(minutes< other.minutes)
true
false
}
overridedef toString():String={
hours +" : "+ minutes
}
}
5.4 重新實現前一個類中的Time類,將內部呈現改成午夜起的分鐘數(介於0到24*60-1之間)。不要改變公有介面。也就是說,客戶端程式碼不應因你的修改而受影響
classTime(private[this] val hrs:Int,private[this] val min:Int){
val minutesInDay = hrs *24+min
def before(other:Time):Boolean={
if(minutesInDay < other.minutesInDay)
true
false
}
overridedef toString():String={
(minutesInDay/60)+" : "+(minutesInDay&60)
}
}
5.5 建立一個Student類,加入可讀寫的JavaBeans屬性name(型別為String)和id(型別為Long)。有哪些方法被生產?(用javap檢視。)你可以在Scala中呼叫JavaBeans的getter和setter方法嗎?應該這樣做嗎?
import scala.beans.BeanProperty
classStudent{
@BeanPropertyvar name:String= _
@BeanPropertyvar id:String= _
}
#scalac student.scala
#javap -c Student
Compiledfrom"student.scala"
publicclassStudent{
public java.lang.String name();
Code:
0: aload_0
1: getfield #14 // Field name:Ljava/lang/String;
4: areturn
publicvoid name_$eq(java.lang.String);
Code:
0: aload_0
1: aload_1
2: putfield #14 // Field name:Ljava/lang/String;
5:return
publicvoid setName(java.lang.String);
Code:
0: aload_0
1: aload_1
2: putfield #14 // Field name:Ljava/lang/String;
5:return
public java.lang.String id();
Code:
0: aload_0
1: getfield #22 // Field id:Ljava/lang/String;
4: areturn
publicvoid id_$eq(java.lang.String);
Code:
0: aload_0
1: aload_1
2: putfield #22 // Field id:Ljava/lang/String;
5:return
publicvoid setId(java.lang.String);
Code:
0: aload_0
1: aload_1
2: putfield #22 // Field id:Ljava/lang/String;
5:return
public java.lang.String getName();
Code:
0: aload_0
1: invokevirtual #27 // Method name:()Ljava/lang/String;
4: areturn
public java.lang.String getId();
Code:
0: aload_0
1: invokevirtual #30 // Method id:()Ljava/lang/String;
4: areturn
publicStudent();
Code:
0: aload_0
1: invokespecial #34 // Method java/lang/Object."<init>":()V
4:return
}
5.6 在5.2節的Person類中提供一個主構造器,將負年齡轉換為0
classPerson(val age:Int){
age =if(age <0)0else age
}
5.7 編寫一個Person類,其主構造器接受一個字串,該字串包含名字,空格和姓,如new Person(“Fred Smith”)。提供只讀屬性firstName和lastName。主構造器引數應該是var,val還是普通引數?為什麼?
classPerson{private[this] val name:String}{
private[this] val tmp = name.split("\\s+")
val firstName = tmp(0)
val lastName = tmp(1)
}
//因為firstName和lastName為只讀,所以用val
5.8 建立一個Car類,以只讀屬性對應制造商,型號名稱,型號年份以及一個可讀寫的屬性用於車牌。提供四組構造器。每個構造器fc都要求製造商和型號為必填。型號年份和車牌可選,如果未填,則型號年份為-1,車牌為空串。你會選擇哪一個作為你的主構造器?為什麼?
classCar(val manufactuer:String, val model:String, val year:Int=-1, val license:String=""){
}
5.10 考慮如下的類
class Employ(val name:String,var salary:Double){
def this(){this(“John Q. Public”,0.0)}
}
重寫該類,使用顯示的欄位定義,和一個預設主構造器。你更傾向於使用哪種形式?為什麼?
classEmploy(){
val name:String="John Q. Public"
val salary:Double=0.0
}