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
 
*/


Ch05 类 - 练习的更多相关文章

  1. Java类的继承与多态特性-入门笔记

    相信对于继承和多态的概念性我就不在怎么解释啦!不管你是.Net还是Java面向对象编程都是比不缺少一堂课~~Net如此Java亦也有同样的思想成分包含其中. 继承,多态,封装是Java面向对象的3大特 ...

  2. enum枚举类

    枚举类可用于定义常量ch01 package edu.nf.demo.ch01; /** * * 枚举类型 */ public enum Color { /** * 红色 */ RED, /** * ...

  3. 《 Java 编程思想》CH05 初始化与清理

    < Java 编程思想>CH05 初始化与清理 用构造器确保初始化 在 Java 中,通过提供构造器,类的设计者可确保每个对象都会得到初始化.Java 会保证初始化的进行.构造器采用与类相 ...

  4. 《 Java 编程思想》CH07 复用类

    复用代码是 Java 众多引人注目的功能之一. Java 可以通过创建类来复用代码,要在使用类的时候不破坏现有代码,有两种方式: 组合:在新的类中使用现有类的对象. 继承:按照现有类的类型来创建新类, ...

  5. 《Java从入门到失业》第五章:继承与多态(5.8-5.10):多态与Object类

    5.8多态 上面我们了解了向上转型,即一个对象变量可以引用本类及子类的对象实例,这种现象称为多态(polymorphism).多态究竟有什么用呢?我们先学习一个知识点. 5.8.1方法重写 前面我们学 ...

  6. C++ 可配置的类工厂

    项目中常用到工厂模式,工厂模式可以把创建对象的具体细节封装到Create函数中,减少重复代码,增强可读和可维护性.传统的工厂实现如下: class Widget { public: virtual i ...

  7. Android请求网络共通类——Hi_博客 Android App 开发笔记

    今天 ,来分享一下 ,一个博客App的开发过程,以前也没开发过这种类型App 的经验,求大神们轻点喷. 首先我们要创建一个Andriod 项目 因为要从网络请求数据所以我们先来一个请求网络的共通类. ...

  8. ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之第二章:利用模型类创建视图、控制器和数据库

    在这一章中,我们将直接进入项目,并且为产品和分类添加一些基本的模型类.我们将在Entity Framework的代码优先模式下,利用这些模型类创建一个数据库.我们还将学习如何在代码中创建数据库上下文类 ...

  9. ASP.NET Core 折腾笔记二:自己写个完整的Cache缓存类来支持.NET Core

    背景: 1:.NET Core 已经没System.Web,也木有了HttpRuntime.Cache,因此,该空间下Cache也木有了. 2:.NET Core 有新的Memory Cache提供, ...

随机推荐

  1. Sublime Text 输入法跟随光标

    通过PackageControl安装“IMESupport”,重启Sublime Text3,即可解决:  注:如项目自述,仅支持Windows.

  2. 隐马尔可夫模型:HMM

    隐马尔可夫模型求解三大问题实例剖析 HMM 模型如图所示: 一.隐马尔可夫模型定义 隐马尔可夫模型由初始概率分布.状态转移概率分布以及观测概率分布确定. 设 Q(图中的q)是所有可能的状态的集合,V( ...

  3. Java多线程:多线程基础知识

    一.线程安全性 定义:多个线程之间的操作无论采用何种执行时序或交替方式,都要保证不变性条件不被破坏     “共享”:变量可以由多个线程同时访问:     “可变”:变量的值在其生命周期内可以发生改变 ...

  4. 【gulp】gulp-file-include 合并 html 文件

    gulp-file-include 是 gulp 插件,它提供了一个 include 方法让我们可以像后端模板那样把公共部分的页面导入进来. 安装依赖包(包括了 gulp-file-include 和 ...

  5. unity3D内嵌android项目

    1.从u3d中导出android工程  工程名为 HS5 2.as(AndroidStudio简写)中新建android工程 MyAndroid 3.HS5 以module方式导入到MyAndroid ...

  6. RxAndroid防止内存泄露

    RxJava并不会自动防止这种情况发生,好在它可以很容易地防止内存泄露.Observable.subscribe()方法会返回一个Subscription对象,这个对象仅仅有两个方法:isSbscri ...

  7. 学习Vue 入门到实战——学习笔记

    闲聊: 自从进了现在的公司,小颖就再没怎么接触vue了,最近不太忙,所以想再学习下vue,就看了看vue相关视频,顺便做个笔记嘻嘻. 视频地址:Vue 入门到实战1.Vue 入门到实战2 学习内容: ...

  8. 解决:Windows安装Composer及全局配置时提示部分.dll结尾的php扩展文件找不到指定的模板

    当安装Composer或者全局配置时出现.dll扩展文件找不到指定模板,如下图: 解决办法: 打开php.ini,将extension_dir 改为绝对路径即可 例如:

  9. 3D Slicer Modify Mouse Event 修改3D Slicer中的鼠标响应事件

    在3D Slicer中,我们如果想在自己写的插件中来修改默认的鼠标响应事件的话,就需要先将原有的响应事件链接删除,然后建立自定义的响应事件链接,然后将自己要实现的功能写在响应事件函数中. 比如Slic ...

  10. 求问ps如何导出单个切片及PS导出所有的切片图像

    在ps里面对图片进行切片,并根据需要弄好切片,利用shift键,可以选择其中部分的切片: 弄好以后,点击“文件”,选择“存储为WEB和设备所用格式”:. 在打开的“存储为WEB和设备所用格式”界面上点 ...