1. 程式人生 > >《快學Scala》習題詳解 第5章 類

《快學Scala》習題詳解 第5章 類

1 改進Counter類,讓它不要在大於Int.maxValue時變為負數
增加一個判斷語句

  private var value = 0
  def increment() { if (value < Int.MaxValue) value += 1 }
  def current() = value

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

  //val 只有getter,沒有setter,depotit/withdraw報錯,訪問不到
  val balance: Double = 0
  def deposit(money: Double) { balance += money }
  def
withdraw(money: Double) { balance -= money }

3 定義一個Time類,加入只讀屬性hours和minutes
另外還有一個檢測時間是否早於另一個時間的方法,before(other:Time):Boolean
Time物件以new Time(hrs,min)方式構建,其中0

class Time {
  var hours: Int = 0
  var mintues: Int = 0
  def getHours = hours
  def getMinutes = mintues
  def this(hrs: Int, min: Int) {
    this
() if (hrs <= 23 && hrs >= 0) { hours = hrs; mintues = min } } def before(other: Time): Boolean = { if (other.getHours == hours) other.getMinutes > mintues else other.getHours > hours } }

4 重新實現Timer類,內部呈現改成字午夜起的分鐘數(介於1-24*60) ,不改變公有介面,也就是說,客戶端不因你的修改而受到影響

  var hours: Int = 0
  var mintues: Int = 0
  var mins = 0
  //  def getHours = hours
  //  def getMinutes = mintues
  def getMins = mins
  def this(hrs: Int, min: Int) {
    this()
    if (hrs <= 23 && hrs >= 0) {
      //      hours = hrs; mintues = min
      mins = hrs * 60 + min
    }
  }
  def before(other: Time): Boolean = {
    getMins > other.getMins
  }
}

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

class Student(@BeanProperty var name: String, @BeanProperty var id: Long) {
}
object se {
  def main(args: Array[String]): Unit = {
    var s1 = new Student("Tom", 200)
    println(s1.getName())
    println(s1.getId())
  }
}

共生成9個方法,主構造器+每個欄位兩對setter/getter(scala+javabean)
輸出:Tom,200,證明可呼叫
6 在5.2節的Person類中加一個主構造器,將負年齡換為0

class Person(var privateage: Int) {
  //主構造器的範圍:類體中除了方法,構造器,欄位均為
  if (privateage < 0) privateage = 0
}

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

class Person(name: String) {
  val firstName: String = name.split(" ")(0)
  val lastName: String = name.split(" ")(1)
  def getFirst = firstName
  def getLast = lastName
} 

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

//主構造器包括所有欄位
//通過val控制屬性為只讀
//車牌為可讀寫,因此主構造器中可有可無,不過設在主構造器中程式碼量要少
class Car(val Producter: String, val types: String, val year: Int, var num: String) {
  def this(Producter: String, types: String) {
    this(Producter, types, -1, "")
  }
  def this(Producter: String, types: String, num: String) {
    this(Producter, types, -1, num)
  }
  def this(Producter: String, types: String, year: Int) {
    this(Producter, types, year, "")
  }
}

9 在Java,C#或C++重做前一個練習。Scala相比之下精簡多少?

public class Car2 {
    private String Producter;
    private String types;
    private String num = "";
    private int year = -1;
    public Car2(String producter, String types, String num, int year) {
        super();
        this.Producter = producter;
        this.types = types;
        this.num = num;
        this.year = year;
    }
}

Java中只定義欄位與主構造器,程式碼量就已經接近
如果加上其它三個構造器,getter/setter,程式碼量會加大3倍左右,scala確實很簡便

10 考慮如下的類
class Employ(val name:String,var salary:Double){
def this(){this(“John Q. Public”,0.0)}
}
重寫該類,使用顯示的欄位定義,和一個預設主構造器。你更傾向於使用哪種形式?為什麼?

class Employee {
  //欄位顯示定義,個人認為就是直接定義在類體
  val name: String = ""
  var salary = 0.0
  def this(name: String, salary: Double) {
    this()
    this.salary = salary
    //    this.name=name //報錯
    // 如果想給name賦值,只能將name設定為var,但設定為var,就會變為可讀寫
    // 因此,設立主構造器時,儘量把只讀的放進主構造器中
  }
}