《快學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,就會變為可讀寫
// 因此,設立主構造器時,儘量把只讀的放進主構造器中
}
}