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. RxSwift之路 1#Swift语法知识准备

    RxSwift之路 1#Swift语法知识准备 在开始学习 RxSwift 之前,一定要对 Swift 相关语法有所了解,否则就很难理解为什么可以这样.关于 Swift 的学习其实只要看看 Swift ...

  2. (7) MySQL数据库备份详解

    对于任何数据库来说,备份都是非常重要的 数据库复制不能取代备份的作用 比如我们由于误操作,在主数据库上删除了一些数据,由于主从复制的时间很短,在发现时,从数据库上的数据可能也已经被删除了, 我们不能使 ...

  3. Asp.Net \uxxx Unicode编码解码

    /// <summary> /// Unicode编码 /// </summary> /// <param name="str"></pa ...

  4. MongoDB GridFS 存储文件

    使用MongoDB的GridFS方式. CSDN: https://blog.csdn.net/qq_32657967/article/details/81534259官方文档: https://do ...

  5. JSP之开发环境搭建

    1.下载JDK1.8(或JDK1.7),并进行安装和配置,主要是配置环境变量JAVA_HOME及Path. 2.下载并配置Tomcat8.0(或Tomcat7.0). Windows平台请下载Tomc ...

  6. python一个简单的websocket测试客户端

    朋友发的,之前在网上一直没找着,先记着 #!/usr/bin/env python import asyncio import websockets import json async def tes ...

  7. 从头配置,开发 cocos2dx 3.14.1

    要使用cocos2dx写一个麻将测试工具. 配置流程如下: 1. 下载安装最新版本的VS(VS2017): https://www.visualstudio.com/zh-hans/downloads ...

  8. LeetCode - 703. Kth Largest Element in a Stream

    Design a class to find the kth largest element in a stream. Note that it is the kth largest element ...

  9. JBPM工作流(二)——数据库表说明

    以下为JBMP的数据库说明(18张): 1 流程配置类数据库表: 1.1 JBPM_PROCESSDEFINITION:流程模版表 字段名 字段含义 主键 外键 ID_ 流程模版标识 √ × NAME ...

  10. 一次完整的从webshell到域控的探索之路

    前言 内网渗透测试资料基本上都是很多大牛的文章告诉我们思路如何,但是对于我等小菜一直是云里雾里. 于是使用什么样的工具才内网才能畅通无阻,成了大家一直以来的渴求. 今天小菜我本着所有师傅们无私分享的精 ...