1. 程式人生 > >快學scala 第五章 讀書筆記及習題答案程式碼

快學scala 第五章 讀書筆記及習題答案程式碼

chapter 5 類

標籤:快學scala

一、筆記

  1. scala類方法預設是公有的,
  1. classCounter{
  2. private val value =0
  3. def increment(){ value +=1}
  4. def current()= value
  5. }
  6. val = myCounter =newCounter//或new Counter()
  7. myCounter.current //ok
  8. 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,每個輔助構造器都必須以一個對先前已定義的其他輔助構造器或主構造器呼叫開始。

  1. classPerson{
  2. privatevar name =""
  3. private vat age =0
  4. defthis(name:String){//輔助構造器
  5. this()//呼叫主構造器
  6. this.name = name
  7. }
  8. defthis(name:String, age:Int){//另一個輔助...
  9. this(name)//呼叫前一個輔助構造器
  10. this.age = age
  11. }
  12. }

class Persion(val name: String, val age: Int){ 
... 

主構造器被編譯成欄位,其值被初始化為構造時傳入的引數。

  1. classPersion(val name:String, val age
    :Int){
  2. println("Just constructed another person")
  3. def description = name +" is "+ age +" years old"
  4. }

二、習題答案

5.1 改進5.1節的Counter類,讓它不要在Int.MaxValue時變成負數

  1. classCount{
  2. privatevar value =0
  3. def increment(){if(value <Int.MaxValue) value +1else value }
  4. def current = value
  5. }

5.2 編寫一個BankAccount類,加入deposit和withdraw方法,和一個只讀的balance屬性

  1. classBankCount(val balance:Int=0){
  2. def deposit(){}
  3. def withdraw(){}
  4. }

5.3 編寫一個Time類,加入只讀屬性hours和minutes,和一個檢查某一時刻是否早於另一時刻的方法before(other:Time):Boolean。Time物件應該以new Time(hrs,min)方式構建。其中hrs以軍用時間格式呈現(介於0和23之間)

  1. classTime(private[this] val hrs:Int,private[this] val min:Int){
  2. val hours = hrs
  3. val minutes = min
  4. def before(other:Time):Boolean={
  5. if(hours < other.hours)
  6. true
  7. if(hours == other.hours)
  8. if(minutes< other.minutes)
  9. true
  10. false
  11. }
  12. overridedef toString():String={
  13. hours +" : "+ minutes
  14. }
  15. }

5.4 重新實現前一個類中的Time類,將內部呈現改成午夜起的分鐘數(介於0到24*60-1之間)。不要改變公有介面。也就是說,客戶端程式碼不應因你的修改而受影響

  1. classTime(private[this] val hrs:Int,private[this] val min:Int){
  2. val minutesInDay = hrs *24+min
  3. def before(other:Time):Boolean={
  4. if(minutesInDay < other.minutesInDay)
  5. true
  6. false
  7. }
  8. overridedef toString():String={
  9. (minutesInDay/60)+" : "+(minutesInDay&60)
  10. }
  11. }

5.5 建立一個Student類,加入可讀寫的JavaBeans屬性name(型別為String)和id(型別為Long)。有哪些方法被生產?(用javap檢視。)你可以在Scala中呼叫JavaBeans的getter和setter方法嗎?應該這樣做嗎?

  1. import scala.beans.BeanProperty
  2. classStudent{
  3. @BeanPropertyvar name:String= _
  4. @BeanPropertyvar id:String= _
  5. }
  6. #scalac student.scala
  7. #javap -c Student
  8. Compiledfrom"student.scala"
  9. publicclassStudent{
  10. public java.lang.String name();
  11. Code:
  12. 0: aload_0
  13. 1: getfield #14 // Field name:Ljava/lang/String;
  14. 4: areturn
  15. publicvoid name_$eq(java.lang.String);
  16. Code:
  17. 0: aload_0
  18. 1: aload_1
  19. 2: putfield #14 // Field name:Ljava/lang/String;
  20. 5:return
  21. publicvoid setName(java.lang.String);
  22. Code:
  23. 0: aload_0
  24. 1: aload_1
  25. 2: putfield #14 // Field name:Ljava/lang/String;
  26. 5:return
  27. public java.lang.String id();
  28. Code:
  29. 0: aload_0
  30. 1: getfield #22 // Field id:Ljava/lang/String;
  31. 4: areturn
  32. publicvoid id_$eq(java.lang.String);
  33. Code:
  34. 0: aload_0
  35. 1: aload_1
  36. 2: putfield #22 // Field id:Ljava/lang/String;
  37. 5:return
  38. publicvoid setId(java.lang.String);
  39. Code:
  40. 0: aload_0
  41. 1: aload_1
  42. 2: putfield #22 // Field id:Ljava/lang/String;
  43. 5:return
  44. public java.lang.String getName();
  45. Code:
  46. 0: aload_0
  47. 1: invokevirtual #27 // Method name:()Ljava/lang/String;
  48. 4: areturn
  49. public java.lang.String getId();
  50. Code:
  51. 0: aload_0
  52. 1: invokevirtual #30 // Method id:()Ljava/lang/String;
  53. 4: areturn
  54. publicStudent();
  55. Code:
  56. 0: aload_0
  57. 1: invokespecial #34 // Method java/lang/Object."<init>":()V
  58. 4:return
  59. }

5.6 在5.2節的Person類中提供一個主構造器,將負年齡轉換為0

  1. classPerson(val age:Int){
  2. age =if(age <0)0else age
  3. }

5.7 編寫一個Person類,其主構造器接受一個字串,該字串包含名字,空格和姓,如new Person(“Fred Smith”)。提供只讀屬性firstName和lastName。主構造器引數應該是var,val還是普通引數?為什麼?

  1. classPerson{private[this] val name:String}{
  2. private[this] val tmp = name.split("\\s+")
  3. val firstName = tmp(0)
  4. val lastName = tmp(1)
  5. }
  6. //因為firstName和lastName為只讀,所以用val

5.8 建立一個Car類,以只讀屬性對應制造商,型號名稱,型號年份以及一個可讀寫的屬性用於車牌。提供四組構造器。每個構造器fc都要求製造商和型號為必填。型號年份和車牌可選,如果未填,則型號年份為-1,車牌為空串。你會選擇哪一個作為你的主構造器?為什麼?

  1. classCar(val manufactuer:String, val model:String, val year:Int=-1, val license:String=""){
  2. }

5.10 考慮如下的類 
class Employ(val name:String,var salary:Double){ 
def this(){this(“John Q. Public”,0.0)} 

重寫該類,使用顯示的欄位定義,和一個預設主構造器。你更傾向於使用哪種形式?為什麼?

  1. classEmploy(){
  2. val name:String="John Q. Public"
  3. val salary:Double=0.0
  4. }