Ch05 类 - 练习

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

*/

来自为知笔记(Wiz)

时间: 2024-11-04 20:26:56

Ch05 类 - 练习的相关文章

类的使用

//定义类 package com.jredu.ch.Package001;public class LvYou { public String name; public int age; public void menpiao(){  if (age>18) {   System.out.println(name+"的年龄为"+age+",门票价格为20");  }else {   System.out.println(name+"的年龄为&quo

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

< Java 编程思想>CH05 初始化与清理 用构造器确保初始化 在 Java 中,通过提供构造器,类的设计者可确保每个对象都会得到初始化.Java 会保证初始化的进行.构造器采用与类相同的名称. 由于构造器的名称必须与类名完全相同,所以"每个方法首字母小写"的风格在这里不适用. 构造器方法可以有参数,这样可以在初始化对象时提供实际参数. 不接受任何参数的构造器叫做"默认构造器". 构造器一种特殊类型的方法,它没有返回值 方法重载 因为可以要用多种方式

jvm系列(一):java类的加载机制

java类的加载机制 原文:http://www.cnblogs.com/ityouknow/p/5603287.html 1.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构.类的加载的最终产品是位于堆区中的Class对象,Class对象封装了类在方法区内的数据结构,并且向Java程序员提供了访问方法区内的数据结构的接口. 类加载器并不需要等到某个

iOS -- SKSpriteNode类

SKSpriteNode类 继承自 SKNode:UIResponder:NSObject 符合 NSCoding(SKNode)NSCopying(SKNode)NSObject(NSObject) 框架  /System/Library/Frameworks/SpriteKit.framework 可用性 可用于iOS 7.0或者更晚的版本 声明于 SKSpriteNode.h 参考指南 Sprite Kit Progamming Guide 概览 重要提示:这是一个初步的API或者开发技术

iOS -- SKScene类

SKScene类 继承自 SKEffectNode:SKNode:UIResponder:NSObject 符合 NSCoding(SKNode)NSCopying(SKNode)NSObject(NSObject) 框架  /System/Library/Frameworks/SpriteKit.framework 可用性 可用于iOS 7.0或者更晚的版本 声明于 SKScene.h 参考指南 Sprite Kit Progamming Guide 概览 重要提示:这是一个初步的API或者开

iOS -- SKPhysicsWorld类

SKPhysicsWorld类 继承自 NSObject 符合 NSCodingNSObject(NSObject) 框架  /System/Library/Frameworks/SpriteKit.framework 可用性 可用于iOS 7.0或者更晚的版本 声明于 SKPhysicsWorld.h 参考指南 Sprite Kit Progamming Guide 概览 重要提示:这是一个初步的API或者开发技术文档.虽然已经审阅了本文档的技术准确性,但是它不是最终的版本.本机密信息仅适用于

C#嵌套类

嵌套类顾名思义就是类或者结构中定义的类 class Container { class Nested { Nested() { } } } <1>嵌套类的默认访问权限是private ,可以指定为public,protected,private,internal,protected internal.<2>嵌套类型可以访问外部类(包裹嵌套类的类),如果要访问外部类型,要把外部类通过构造函数传进一个实例<3>嵌套类中只能访问外部类中的静态成员,不能直接访问外部类的非静态成

一个实用的C#网页抓取类代码分享

一个实用的C# 网页抓取类 模拟蜘蛛,类中定义了超多的C#采集文章.网页抓取文章的基础技巧,下面分享代码: using System; using System.Data; using System.Configuration; using System.Net; using System.IO; using System.Text; using System.Collections.Generic; using System.Text.RegularExpressions; using Sys

类图(Rose) - Windows XP经典软件系列

最近开始了自己高级数据结构之旅,在这次旅行中,我将持续把一些高级的数据结构从理论到编码都过一遍,同时通过博客形式分享出来,希望大家指出不足之处! 二叉排序树是一种动态排序的数据结构,支持插入.删除.查找等操作,且平均时间复杂度为O(log(N)),但是普通二叉排序树不能保证树退化为一颗分支的情况,此时最坏情况下的时间复杂度为O(N).此时,平衡二叉树的产生了.平衡二叉树是一种动态调整平衡的数据结构,但理想的平衡二叉树很难,于是人们使用AVL.红黑树.Treap.伸展树等来替代平衡二叉树,这些数据