《快学Scala》(英文版:《Scala for the Impatient》),代码已传github:
https://github.com/vernonzheng/scala-for-the-Impatient
书为第一版。scala为2.11.4,jdk1.7.45,操作系统Mac OS X Yosemite 10.10.1。
第五章 类
5.1
改进5.1节的Counter类,让它不要在Int.MaxValue时变成负数
答:
1 2 3 4 5
| class Counter(){ private var value = 0 def increment(){ if(value<Int.MaxValue) value += 1 } def current() = value }
|
5.2
编写一个BankAccount类,加入deposit和withdraw方法,和一个只读的balance属性
答:
1 2 3 4 5
| class BankAccount{ private val banlance = 0 def deposit(){} def withdraw(){} }
|
5.3
编写一个Time类,加入只读属性hours和minutes,和一个检查某一时刻是否早于另一时刻的方法before(other:Time):Boolean。Time对象应该以new Time(hrs,min)方式构建。其中hrs以军用时间格式呈现(介于0和23之间)
答:
1 2 3 4 5 6 7 8 9 10 11 12
| class Time(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 } }
|
5.4
重新实现前一个类中的Time类,将内部呈现改成午夜起的分钟数(介于0到24*60-1之间)。不要改变公有接口。也就是说,客户端代码不应因你的修改而受影响
答:
1 2 3 4 5 6 7 8
| class Time(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 } }
|
5.5
创建一个Student类,加入可读写的JavaBeans属性name(类型为String)和id(类型为Long)。有哪些方法被生产?(用javap查看。)你可以在Scala中调用JavaBeans的getter和setter方法吗?应该这样做吗?
答:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| import scala.beans.BeanProperty class Student{ @BeanProperty var name:String = _ @BeanProperty var id:Long = _ } /** javap -c Student 后显示如下 Compiled from "Student.scala" public class Student extends java.lang.Object implements scala.ScalaObject{ public java.lang.String name(); Code: 0: aload_0 1: getfield #13; //Field name:Ljava/lang/String; 4: areturn public void name_$eq(java.lang.String); Code: 0: aload_0 1: aload_1 2: putfield #13; //Field name:Ljava/lang/String; 5: return public void setName(java.lang.String); Code: 0: aload_0 1: aload_1 2: putfield #13; //Field name:Ljava/lang/String; 5: return public long id(); Code: 0: aload_0 1: getfield #19; //Field id:J 4: lreturn public void id_$eq(long); Code: 0: aload_0 1: lload_1 2: putfield #19; //Field id:J 5: return public void setId(long); Code: 0: aload_0 1: lload_1 2: putfield #19; //Field id:J 5: return public long getId(); Code: 0: aload_0 1: invokevirtual #25; //Method id:()J 4: lreturn public java.lang.String getName(); Code: 0: aload_0 1: invokevirtual #28; //Method name:()Ljava/lang/String; 4: areturn public Student(); Code: 0: aload_0 1: invokespecial #34; //Method java/lang/Object."<init>":()V 4: return } **/
|
5.6
在5.2节的Person类中提供一个主构造器,将负年龄转换为0
答:
1 2 3
| class Person(var age:Int){ age = if(age < 0) 0 else age }
|
5.7
编写一个Person类,其主构造器接受一个字符串,该字符串包含名字,空格和姓,如new Person(“Fred Smith”)。提供只读属性firstName和lastName。主构造器参数应该是var,val还是普通参数?为什么?
答:
1 2 3 4 5
| class Person(private[this] val name:String){ private[this] val tmp = name.split("\\s+") val firstName = tmp(0) val lastName = tmp(1) }
|
5.8
创建一个Car类,以只读属性对应制造商,型号名称,型号年份以及一个可读写的属性用于车牌。提供四组构造器。每个构造器fc都要求制造商和型号为必填。型号年份和车牌可选,如果未填,则型号年份为-1,车牌为空串。你会选择哪一个作为你的主构造器?为什么?
答:
1
| class Car(val manufactuer:String, val model: String, val year: Int = -1, var license: String = "")
|
5.9
在Java,C#或C++重做前一个练习。Scala相比之下精简多少?
答:
略
5.10
考虑如下的类
class Employ(val name:String,var salary:Double){
def this(){this(“John Q. Public”,0.0)}
}
重写该类,使用显示的字段定义,和一个缺省主构造器。你更倾向于使用哪种形式?为什么?
答:
1 2 3 4
| class Employ(){ val name:String = "John Q. Public" var salary:Double = 0.0 }
|
参考:
《快学Scala》:http://book.douban.com/subject/19971952/
(转载本站文章请注明作者和出处 Vernon Zheng(郑雪峰) – vernonzheng.com ,请勿用于任何商业用途)