1. 改进5.1节的Counter类,让它不要在Int.MaxValue是变成负数。

class Counter{
    private var value = Int.MaxValue
    def increment() { value = if ( value < Int.MaxValue) value + 1 else value }
    def current = value
}
 
val myCounter = new Counter()
myCounter.increment()
println(myCounter.current)
 
/*result
2147483647
*/

2.  编写一个BankAccount类,加入deposit和withdraw方法,和一个只读的balance属性。
class BankAccount(val balance:Double=0.0){
    def deposit() {}
    def withdraw() {}
}
 
val obj = new BankAccount(100.00)
println(obj.balance)
 
/*result
100.0
*/

3. 编写一个Time类,加入只读属性hours和minutes,和一个检查某一时刻是否早于另一时刻的方法before(other: Time): Boolean。
Time对象应该以new Time(hrs, min)方式构建,其中hrs小时数以军用时间格式呈现(介于0和23之间)。

class Time(val hours:Int, val minutes:Int){
    def before(other:Time):Boolean={
        if(hours == other.hours) minutes < other.minutes
        else hours < other.hours
    }
}
val = new Time(9,0)
val = new Time(9,0)
val = new Time(9,30)
val = new Time(10,0)
 
println(a.before(b))
println(a.before(c))
println(a.before(d))
 
/*result
false
true
true
*/


4. 重新实现前一个练习中的Time类,将内部呈现改成自午夜起的分钟数(介于0到24x60-1之间)。不要改变公有接口。也就是说,客户端代码不应因你的修改而受到影响。

class Time(val hours:Int, val minutes:Int){
    private val timeMinutes = hours * 60 + minutes
     
    def before(other:Time):Boolean={
        timeMinutes < other.timeMinutes
    }
}
val = new Time(9,0)
val = new Time(9,0)
val = new Time(9,30)
val = new Time(10,0)
 
println(a.before(b))
println(a.before(c))
println(a.before(d))
 
/*result
false
true
true
*/

5. 创建一个Student类,加入可读写的JavaBeans属性name(类型为String)和id(类型为Long)。有哪些方法被生成?(用javap查看。)
你可以在Scala中调用JavaBeans版的getter和setter方法吗?应该这样做吗?
回答:有以下方法被生成:
  public java.lang.String name();
  public void name_$eq(java.lang.String);

public java.lang.String getName();
  public void setName(java.lang.String);

  public long id();
  public void id_$eq(long);

  public long getId();
  public void setId(long);
  

在Scala中调用JavaBean版的getter和setter是可以的。除非是为了工具的兼容性,不推荐这样做。因为这样做破坏了Scala的编程风格。


import scala.beans.BeanProperty
 
class Student{
    @BeanProperty var name: String = _
    @BeanProperty var id: Long = _
}
 
val = new Student
a.name = "Jonathan"
a.id = 43344506L
printf("%s's id is %d\n", a.name, a.id)
 
a.setName("Frank")
a.setId(43344599L)
printf("%s's id is %d\n", a.getName(), a.getId())
 
 
/*result
G:\share\scala>scalac e5-5.scala
 
G:\share\scala>javap Student.class
Compiled from "e5-5.scala"
public class Student {
  public java.lang.String name();
  public void name_$eq(java.lang.String);
  public void setName(java.lang.String);
  public long id();
  public void id_$eq(long);
  public void setId(long);
  public java.lang.String getName();
  public long getId();
  public Student();
}
 
G:\share\scala>scala e5-5.scala
Jonathan's id is 43344506
Frank's id is 43344599
*/

6. 在5.2节的Person类中提供一个主构造器,将负年龄转换为0。
class Person(var age:Int){
    if(age<0) age = 0
}
 
val = new Person(-1)
printf("The person's age is %d\n", a.age)
 
 
/*result
The person's age is 0
*/

7. 编写一个Person类,其主构造器接受一个字符串,该字符串包含名字、空格和姓,如new Person("Fred Smith")。
提供只读属性firstName和lastName。主构造器的参数应该是var、val还是普通参数呢?为什么?

语法上都没有错,但从逻辑上看,应该使用val。如果为var,则对应的此字符串有getter和setter方法,而Person中的firstName和lastName为只读的,
所以不能重复赋值。

class Person(val name:String){
    val firstName = name.split(" ")(0)
    val lastName = name.split(" ")(1)
}
 
val = new Person("Jonathan Chen")
printf("The person's lastName is %s\n", a.lastName)
printf("The person's firstName is %s\n", a.firstName)
 
 
 
/*result
The person's lastName is Chen
The person's firstName is Jonathan
*/

8. 创建一个Car类,以只读属性对应制造商、型号名称、型号年份以及一个可读写的属性用于车牌。提供四组构造器。
每一个构造器都要求制造商和型号名称为必填。型号年份以及车牌为可选,如果未填,则型号年份设置为-1,车牌设置为空字符串。
你会选择哪一个作为你的主构造器?为什么?
选择 Car(val maker:String, val typeName:String, val year:Int, var id:String) 为主构造器,因为所有的辅助构造器都可以引用主构造器。
class Car(val maker:String, val typeName:String, val year:Int, var id:String){
    def this(maker:String, typeName:String){
        this(maker, typeName, -1"")
    }
    def this(maker:String, typeName:String, year:Int){
        this(maker, typeName, year, "")
    }
    def this(maker:String, typeName:String, id:String){
        this(maker, typeName, -1, id)
    }
    override def toString = "Maker:%s, TypeName:%s, Year:%d, Id:%s".format(maker, typeName, year, id)
}
val = new Car("BMW","A6")
val = new Car("BMW","A6",2015,"TheOne")
val = new Car("BMW","A6",2015)
val = new Car("BMW","A6","TheOne")
 
println(a)
println(b)
println(c)
println(d)
 
/*result
Maker:BMW, TypeName:A6, Year:-1, Id:
Maker:BMW, TypeName:A6, Year:2015, Id:TheOne
Maker:BMW, TypeName:A6, Year:2015, Id:
Maker:BMW, TypeName:A6, Year:-1, Id:TheOne
*/


9. 在Java、C#或C++(你自己选)重做前一个练习。Scala相比之下精简多少?
略。本书P60页对此有所比较。

10.  考虑如下类:
class Employee(val name:String, var salary:Double){
    def this() { this("Join Q. Public", 0.0) }
}
重写该类,使用显式的字段定义,和一个缺省主构造器。你更倾向于使用哪一种形式?为什么?
这两种写法并不完全等价。第一种写法有两组构造器,而第二种写法只有默认的主构造器。

class Employee{
    val name:String = "Join Q. Public"
    var salary:Double = 0.0
}
 
val = new Employee
 
/*result
 
*/


最新文章

  1. php工厂方法
  2. 截取UIImage指定大小区域
  3. selenium处理滚动条
  4. OpenJudge计算概论-求出e的值
  5. Winform的多线程问题
  6. JS中面向对象的,对象理解、构造函数、原型、原型链
  7. Clash of Clans(COC)资源压缩解密
  8. sublime text 3双击选择无法选择$符号
  9. 基于Quartz实现简单的定时发送邮件
  10. 关于将dede织梦data目录迁移出web目录
  11. WPF中自定义标题栏时窗体最大化处理之WindowChrome
  12. [LeetCode] Convert Binary Search Tree to Sorted Doubly Linked List 将二叉搜索树转为有序双向链表
  13. Delphi ClientDataSet 主从结构 BUG
  14. 模板, 保存&amp;发布
  15. vim命令详解
  16. ES6之导入模块时的内存共享
  17. JS继承实现的几种方式
  18. Linux 管道
  19. qt——for循环里创建widget
  20. 浅谈ASP.net中的DataSet对象

热门文章

  1. 训练的时候 nvidia:自动刷新
  2. h5 扫描二维码打开app和点击下载功能的实现
  3. Mysql数据按天分区,定期删除
  4. java通过jdbc访问mysql,update数据返回值的思考
  5. 删除maven仓库中的LastUpdated文件
  6. Mysql Window 解压版卸载
  7. JS设计模式——工厂模式详解
  8. (二)区块链的共识算法:PoS 及其 例子 代码 实现
  9. 11.7luffycity项目(2)
  10. mac 远程连接 云服务器