知识点:

1.简单类和无参方法

class Counter {
private var value = 0 //必须初始化字段
def increment() { value += 1} //方法默认是公有的
def current() = value
}

在Scala中,类并不声明为public,Scala源文件可以包含多个类,所有这些类都具有共有可见性。

val myCounter = new Counter //or new Counter()
myCounter.increment()
println(myCounter.current())

调用无参方法,可以写上圆括号,也可以不写。对于改值器方法(即改变对象状态的方法)使用(),对于取值器方法(不会改变对象状态的方法)去掉().可以通过以不带()的方式声明current来使用不带圆括号的风格。

2.带gettter和setter的属性

Scala生成面向JVM的类,对于声明的字段都会提供getter和setter方法。在Scala中,getter和setter分别叫做age和age_=,可以重新定义getter和setter方法。

  • 对于私有字段而言,getter和setter方法也是私有的;
  • 如果字段是val, 则只有getter方法被生成;
  • 如果你需要任何getter和setter,可以将字段声明为 private[this].

颇具影响的Eiffel语言的发明者Bertrand Meyer提出了“ 统一访问原则”:某个模块提供的所有服务都应该能通过统一的表示法访问到,至于它们是通过存储还是通过计算来实现的,从访问方式上应无从可知。Scala符合这个原则。

3.只带getter的属性

如果属性的值在对象构建完成后不再改变,则可以使用val字段,scala会生成一个私有的final字段和getter方法。总结一下,在实现属性时有如下四个选择:

  • var foo: Scala自动合成一个getter和setter方法
  • val foo: Scala自动合成一个getter
  • 由你来定义foo和foo_=方法
  • 由你来定义foo方法

当你在Scala类中看到字段的时候,它代表的是一个私有字段加上getter方法(对val字段)或者getter和setter方法(对var字段而言)。

4.对象私有字段

private[this]修饰字段时,表明某个对象.value这样的访问不被允许。类定义的方法只能访问到当前对象的value字段,而不能访问同样类的其他对象的字段,这样的访问被称为对象私有的。

对于类私有的字段,Scala生成私有的getter和setter方法,而对于对象私有的字段,Scala不会生成getter和setter方法。

5.Bean属性

将Scala字段标注为@BeanProperty时,会自动生成getFoo/setFoo这样的方法。

Scala字段 生成的方法 何时使用
val/var name 公有的name

name_=(仅限于var)
实现一个可以被公开访问并且背后是以一个字段形式保存的属性
@BeanProperty val/var name 公有的name

getName()

name_=(仅限于var)

setName(…) (仅限于var)

与JavaBean互操作
private val/var name 私有的name

name_=(仅限于var)
用于将字段访问限制在本类的方法,就和Java一样,尽量使用private——除非你真的需要一个公有的属性
private[this] val/var name 用于将字段访问限制在同一个对象上调用的方法,并不经常用到
private[类名] val/var name 依赖于具体实现 将访问权赋予外部类,不经常用到

6.辅助构造器

1)辅助构造器的名称为this

2)每一个辅助构造器都必须以一个对先前已定义的其他辅助构造器或猪狗在其的调用开始。

如果没有显示定义主构造器则自动拥有一个无参的主构造器。

class Person{
private var age = 0
private var name = "" def this(name:String){
this()
this.name=name
} def this(name:String,age:Int){
this(name)
this.age = age
}
}

7.主构造器

1)主构造器的参数直接放置在类名后

2)主构造器会执行类定义中的所有语句

如果类名之后没有参数,则该类具备一个无参主构造器。通常可在主构造器中使用默认参数来避免过多的使用辅助构造器。构造参数可以是普通的方法参数,不带val或var,这样的参数如何处理取决于它们在类中如何被使用。如果不带val或var的参数至少被一个方法所使用,它将被升格为字段;否则,该参数将不被保存为字段,仅仅是一个可以被主构造器中的代码访问的普通参数。

class Person(name:String,age:Int){
def description = name + " is " + age + " years old"
}
//声明和初始化了不可变字段name、age,这两个字段都是对象私有的,等同于private[this] val字段的效果

针对主构造器参数生成的字段和方法

主构造器参数 生成的字段/方法
name: String 对象私有字段,如果没有方法使用那么,则没有该字段
private val/var name: String 私有字段,私有的getter/setter方法
val/var name: String 私有字段,公有的getter/setter方法
@BeanProperty val/var: String 私有字段,公有的Scala版和JavaBean版的getter/setter方法

8.嵌套类

在Scala中,几乎可以在任何语法结构中内嵌任何语法结构,在任何函数中定义函数,在类中定义类。


练习:(参考网址

1.改进5.1节的Counter类,让它不要在Int.MaxValue时变成负数

class Counter {
private var value = 0 //必须初始化字段
def increment() {
if(value < Int.MaxValue){
value += 1
}
else value } //方法默认是公有的
def current() = value
}

2.编写一个BankAccount类,加入deposit和withdraw方法,和一个只读的balance属性

class BankAccount{
val balance = 0
def deposit(amount:Double) {}
def withdraw(){}
}

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={
hours < other.hours || (hours == other.hours && minutes < other.minutes)
} override def toString():String={
hours + " : " + minutes
}
}

4.重新实现前一个类中的Time类,将内部呈现改成午夜起的分钟数(介于0到24*60-1之间)。不要改变公有接口。也就是说,客户端代码不应因你的修改而受影响

class Time(val hours:Int,val minutes:Int){

   def before(other:Time):Boolean={
hours < other.hours || (hours == other.hours && minutes < other.minutes)
} override def toString():String={
(hours * 60 + minutes)+""
}
}

5.创建一个Student类,加入可读写的JavaBeans属性name(类型为String)和id(类型为Long)。有哪些方法被生产?(用javap查看。)你可以在Scala中调用JavaBeans的getter和setter方法吗?应该这样做吗?

import scala.beans.BeanProperty
//答案里导入的包 scala2.11.8没有这个类了,在API中查找包位置
class Student {
@BeanProperty var name:String = _
@BeanProperty var id:Long = _
}

javap –c Student 查看 生成了name()\name_=\setName()\getName()   id()\id_=\setId()\getId()

Compiled from "Student.scala"
public class Student {
public java.lang.String name();
Code:
0: aload_0
1: getfield #15 // Field name:Ljava/lang/String;
4: areturn public void name_$eq(java.lang.String);
Code:
0: aload_0
1: aload_1
2: putfield #15 // Field name:Ljava/lang/String;
5: return public void setName(java.lang.String);
Code:
0: aload_0
1: aload_1
2: putfield #15 // Field name:Ljava/lang/String;
5: return public long id();
Code:
0: aload_0
1: getfield #24 // Field id:J
4: lreturn public void id_$eq(long);
Code:
0: aload_0
1: lload_1
2: putfield #24 // Field id:J
5: return public void setId(long);
Code:
0: aload_0
1: lload_1
2: putfield #24 // Field id:J
5: return public java.lang.String getName();
Code:
0: aload_0
1: invokevirtual #30 // Method name:()Ljava/lang/String;
4: areturn public long getId();
Code:
0: aload_0
1: invokevirtual #33 // Method id:()J
4: lreturn public Student();
Code:
0: aload_0
1: invokespecial #37 // Method java/lang/Object."<init>":
()V
4: return
}

6.在5.2节的Person类中提供一个主构造器,将负年龄转换为0

class Person(var age:Int){
age = if(age < 0) 0 else age
}

7.编写一个Person类,其主构造器接受一个字符串,该字符串包含名字,空格和姓,如new Person("Fred Smith")。提供只读属性firstName和lastName。主构造器参数应该是var,val还是普通参数?为什么?

val,如果为var的话,对应的字符串有get和set方法,因为只提供只读属性firstName和lastName,不能重复赋值。

8.创建一个Car类,以只读属性对应制造商,型号名称,型号年份以及一个可读写的属性用于车牌。提供四组构造器。每个构造器fc都要求制造商和型号为必填。型号年份和车牌可选,如果未填,则型号年份为-1,车牌为空串。你会选择哪一个作为你的主构造器?为什么?

class Car(val maker:String,val typeName:String){

辅助构造器参数分别为 型号年份、车牌、型号年份和车牌,不知道对不。

9.考虑如下的类

class Employ(val name:String,var salary:Double){ 
    def this(){this("John Q. Public",0.0)} 

重写该类,使用显示的字段定义,和一个缺省主构造器。你更倾向于使用哪种形式?为什么?

class Employ{
val name:String = "John Q. Public"
var salary:Double = 0.0
}

2

快学Scala-第五章 类的更多相关文章

  1. 快学Scala 第6章 对象 - 练习

    1. 编写一个Conversions对象,加入inchesToCentimeters.gallonsToLiters和milesToKilometers方法. object Conversions { ...

  2. 快学Scala 第五课 (构造映射,获取映射值,更新映射值,迭代映射,与Java互操作)

    构造映射: val score = Map[String, Int]() val score1 = HashMap[String, Int]() val value1 = Map[String, In ...

  3. 《快学Scala》第二章 控制结构和函数

  4. 《快学Scala》第一章 基础

  5. 快学Scala习题解答—第一章 基础

    1 简介 近期对Scala比较感兴趣,买了本<快学Scala>,感觉不错.比<Programming Scala:Tackle Multi-Core Complexity on th ...

  6. 《快学Scala》

    Robert Peng's Blog - https://mr-dai.github.io/ <快学Scala>Intro与第1章 - https://mr-dai.github.io/S ...

  7. 快学Scala 第十九课 (trait的abstract override使用)

    trait的abstract override使用: 当我看到abstract override介绍的时候也是一脸懵逼,因为快学scala,只介绍了因为TimestampLogger中调用的super ...

  8. 简学Python第五章__模块介绍,常用内置模块

    Python第五章__模块介绍,常用内置模块 欢迎加入Linux_Python学习群  群号:478616847 目录: 模块与导入介绍 包的介绍 time &datetime模块 rando ...

  9. [Scala] 快学Scala A2L2

    集合 13.1 集合的三大类 所有的集合都扩展Iterable特质.集合的三大集合为Seq, Set, Map Seq是一个有先后次序的值的序列,比如数组或列表.IndexSeq允许我们通过整型下表快 ...

  10. 《快学Scala》——控制结构和函数

    条件表达式 在Scala中if/else表达式有值,这个值就是跟在if或else之后的表达式的值.例如: if (x > 0) 1 else -1 上述表达式的值是1或-1,具体是哪一个取决于x ...

随机推荐

  1. 判断一个数是否为2的n次幂

    参考:http://bbs.csdn.net/topics/370058619 如题,如何判断一个整数是否是2的N次方,我能想到的方法有两个 1.一直除2,看最后是否等于1.(最笨的方法) 2.转换成 ...

  2. 使用InternetReadFile时要注意读取完整数据

    使用这个api读取数据后,即使数据不完整,该函数不会报任何错,GetLastError也显示操作成功.使用时要注意通过其参数判断是否读取完毕 void InternetReadFileEx(HINTE ...

  3. NOIP2011-普及组复赛模拟试题-第一题-NBA总冠军

    题目背景 Background 一年两度的期末考要到来了!!  题目描述 Description   又要到考试了,Ljw决定放松一下,就打开电视,看见了篮球赛,他立即想到了每年的NBA总冠军队伍.由 ...

  4. 通过httplib2 探索的学习的最佳方式

    在工作中需要对一个视频点播两百次,使其成为热门视频,才能对其p2p情况进行测试.虽然可以手动点播两百次,但是利用python发送200次post请求,能减少很多的工作量.该发送请求的方法用到了http ...

  5. Ubuntu11.10 E: Unable to locate package ubuntu-restricted-extras

    最近在ubuntu11.10下安装支持多媒体播放的插件时遇到一些问题,在此小记一下. 首先是ubuntu11.10的安装,基本上是一键安装,在此不细说. 1.此版本和以前使用的ubuntu版本风格不太 ...

  6. redis3--key的操作

    我们之前使用Redis简单存储了三个参数:在语句set name jack中,其中name就是一个key.我们Java中的变量名是有一定规则的,比如组成内容可以是"数字",&quo ...

  7. [WPF] 浏览百度地图并获取经纬度地址信息

    项目中需要利用登记的区域和地址在百度地图上定位,并获取该地址的经纬度. 本次功能对我来说主要难点如下:1.百度地图API的基本使用方法,请首选使用百度地图的JavaScript大众版(PS:之前使用W ...

  8. (响应式PC端媒体查询)电脑屏幕分辨率尺寸大全

    (响应式PC端媒体查询)电脑屏幕分辨率尺寸大全 时间:2015-08-17 16:50:40      阅读:3961      评论:0      收藏:0      [点我收藏+] 标签:styl ...

  9. Windows API 之 FormatMessage

    FormatMessage Formats a message string. The function requires a message definition as input. The mes ...

  10. java写文件时,输出不完整的原因以及解决方法close()或flush()

    在java的IO体系中,写文件通常会用到下面语句 BufferedWriter bw=new BufferedWriter(new FileWriter("sql语句.txt")) ...