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. [HDFS Manual] CH8 HDFS Snapshots

    HDFS Snapshots HDFS Snapshots 1. 概述 1.1 Snapshottable目录 1.2 快照路径 2. 带快照的更新 3. 快照操作 3.1 管理操作 3.2 用户操作 ...

  2. [HDFS Manual] CH3 HDFS Commands Guide

    HDFS Commands Guide HDFS Commands Guide 3.1概述 3.2 用户命令 3.2.1 classpath 3.2.2 dfs 3.2.3 envvars 3.2.4 ...

  3. mybatis-generator 自动生成查询Vo

    package com.witwicky.plugins; import org.mybatis.generator.api.GeneratedJavaFile; import org.mybatis ...

  4. Android开发怎么让自己的APP UI漂亮、大方(规范篇一)

    首先,笔者是站立在开发者的角度来看UI设计的,欢迎专业人士提供指导,不多说,来看怎么把UI设计和开发高效结合起来~ 一.约定APP开发中的一些规则 1.大部分图标满足HDPI(高清)即可,比如:大众点 ...

  5. 【转】WPF自定义控件与样式(11)-等待/忙/正在加载状态-控件实现

    一.前言 申明:WPF自定义控件与样式是一个系列文章,前后是有些关联的,但大多是按照由简到繁的顺序逐步发布的等. 本文主要有三种实现方式: 简单忙碌状态控件BusyBox: Win8/win10效果忙 ...

  6. laravel5.8笔记五:基类控制器和基类模型

    建立基类的目的就是为了方便继承.比如:Admin模块访问,是否登陆.检测登陆可以写到基类里面 控制器基类 原始基类:app\Http\Controllers\Controller.php,我们下面要做 ...

  7. Java接口的幂等性设计

    转载:https://www.cnblogs.com/jack87224088/p/8688948.html 在微服务架构下,我们在完成一个订单流程时经常遇到下面的场景: 一个订单创建接口,第一次调用 ...

  8. 使用PsExec获取shell执行命令

    PsExec PsExec是pstools工具组套件的一部分,确成为了渗透利器,下载地址:点击这里下载 连接shell 我的Windows Server 2012默认打开域网络防火墙的时候,是不能连接 ...

  9. java课程课后作业04之动手动脑

    一.多层的异常捕获-1 先贴出代码: public class CatchWho { public static void main(String[] args) { try { try { thro ...

  10. 接口自动化测试 (三)request.post

    上一节介绍了  requests.get()  方法的基本使用,本节介绍  requests.post()  方法的使用: 本文目录: 一.方法定义 二.post方法简单使用 1.带数据的post 2 ...