chapter 5 类
标签:快学scala
一、笔记
- scala类方法默认是公有的,
class Counter{
private val value = 0
def increment() { value += 1}
def current() = value
}
val = myCounter = new Counter //或new Counter()
myCounter.current //ok
println(myCounter.current)
对于改值器方法使用(),对于取值器则去掉()。
2. java中getter和setter方法比公有字段更好。scala生成面向JVM的类。实现属性时有四个选择:
a. var foo:Scala自动合成一个getter和一个setter.
b. var foo:Scala自动合成一个getter
c. 由你来定义foo和foo_=方法
d. 由你来定义foo方法
所以scala中不能只写属性(只带有settter没有gettter的属性)。
3. 辅助构造器的名称为this,每个辅助构造器都必须以一个对先前已定义的其他辅助构造器或主构造器调用开始。
class Person{
private var name = ""
private vat age = 0
def this(name: String){ //辅助构造器
this() //调用主构造器
this.name = name
}
def this(name: String, age: Int){ //另一个辅助...
this(name) //调用前一个辅助构造器
this.age = age
}
}
class Persion(val name: String, val age: Int){
...
}
主构造器被编译成字段,其值被初始化为构造时传入的参数。
class Persion(val name: String, val age: Int){
println("Just constructed another person")
def description = name + " is " + age + " years old"
}
二、习题答案
5.1 改进5.1节的Counter类,让它不要在Int.MaxValue时变成负数
class Count{
private var value = 0
def increment(){if(value < Int.MaxValue) value + 1 else value }
def current = value
}
5.2 编写一个BankAccount类,加入deposit和withdraw方法,和一个只读的balance属性
class BankCount(val balance: Int = 0){
def deposit(){}
def withdraw(){}
}
5.3 编写一个Time类,加入只读属性hours和minutes,和一个检查某一时刻是否早于另一时刻的方法before(other:Time):Boolean。Time对象应该以new Time(hrs,min)方式构建。其中hrs以军用时间格式呈现(介于0和23之间)
class Time(private[this] val hrs: Int, private[this] val min: Int){
val hours = hrs
val minutes = min
def before(other: Time):Boolean= {
if(hours < other.hours)
true
if(hours == other.hours)
if(minutes< other.minutes)
true
false
}
override def toString():String={
hours + " : " + minutes
}
}
5.4 重新实现前一个类中的Time类,将内部呈现改成午夜起的分钟数(介于0到24*60-1之间)。不要改变公有接口。也就是说,客户端代码不应因你的修改而受影响
class Time(private[this] val hrs: Int, private[this] val min: Int){
val minutesInDay = hrs * 24+min
def before(other: Time):Boolean= {
if(minutesInDay < other.minutesInDay)
true
false
}
override def toString():String={
(minutesInDay/60) + " : " + (minutesInDay&60)
}
}
5.5 创建一个Student类,加入可读写的JavaBeans属性name(类型为String)和id(类型为Long)。有哪些方法被生产?(用javap查看。)你可以在Scala中调用JavaBeans的getter和setter方法吗?应该这样做吗?
import scala.beans.BeanProperty
class Student{
@BeanProperty var name: String = _
@BeanProperty var id: String = _
}
#scalac student.scala
#javap -c Student
Compiled from "student.scala"
public class Student {
public java.lang.String name();
Code:
0: aload_0
1: getfield #14 // Field name:Ljava/lang/String;
4: areturn
public void name_$eq(java.lang.String);
Code:
0: aload_0
1: aload_1
2: putfield #14 // Field name:Ljava/lang/String;
5: return
public void setName(java.lang.String);
Code:
0: aload_0
1: aload_1
2: putfield #14 // Field name:Ljava/lang/String;
5: return
public java.lang.String id();
Code:
0: aload_0
1: getfield #22 // Field id:Ljava/lang/String;
4: areturn
public void id_$eq(java.lang.String);
Code:
0: aload_0
1: aload_1
2: putfield #22 // Field id:Ljava/lang/String;
5: return
public void setId(java.lang.String);
Code:
0: aload_0
1: aload_1
2: putfield #22 // Field id:Ljava/lang/String;
5: return
public java.lang.String getName();
Code:
0: aload_0
1: invokevirtual #27 // Method name:()Ljava/lang/String;
4: areturn
public java.lang.String getId();
Code:
0: aload_0
1: invokevirtual #30 // Method id:()Ljava/lang/String;
4: areturn
public Student();
Code:
0: aload_0
1: invokespecial #34 // Method java/lang/Object."<init>":()V
4: return
}
5.6 在5.2节的Person类中提供一个主构造器,将负年龄转换为0
class Person(val age: Int){
age = if(age < 0) 0 else age
}
5.7 编写一个Person类,其主构造器接受一个字符串,该字符串包含名字,空格和姓,如new Person(“Fred Smith”)。提供只读属性firstName和lastName。主构造器参数应该是var,val还是普通参数?为什么?
class Person{private[this] val name: String}{
private[this] val tmp = name.split("\\s+")
val firstName = tmp(0)
val lastName = tmp(1)
}
//因为firstName和lastName为只读,所以用val
5.8 创建一个Car类,以只读属性对应制造商,型号名称,型号年份以及一个可读写的属性用于车牌。提供四组构造器。每个构造器fc都要求制造商和型号为必填。型号年份和车牌可选,如果未填,则型号年份为-1,车牌为空串。你会选择哪一个作为你的主构造器?为什么?
class Car(val manufactuer: String, val model: String, val year: Int = -1, val license: String = ""){
}
5.10 考虑如下的类
class Employ(val name:String,var salary:Double){
def this(){this(“John Q. Public”,0.0)}
}
重写该类,使用显示的字段定义,和一个缺省主构造器。你更倾向于使用哪种形式?为什么?
class Employ(){
val name: String = "John Q. Public"
val salary: Double = 0.0
}