简单类和无参方法
|
classCounter{
privatevarvalue=0// 必须初始化字段
defincrement(){value+=1}// 方法默认公有
defcurrent()=value
}
|
Scala中的类不声明为public,一个Scala源文件中可以有多个类。
|
valmyCounter=newCounter// 或new Counter()
myCounter.increment()
|
调用无参方法时,圆括号是可写可不写的。推荐的做法是:如果是会改变对象状态的方法,就带上( );否则,就不带。
如果将方法的声明改为以下形式,那么可以强制不能带( )(下面要提到的getter就是这种风格的,所以调用getter时,必须不带( )):
|
classCounter{
privatevarvalue=0// 必须初始化字段
defincrement(){value+=1}// 方法默认公有
defcurrent=value// 调用必须是myCounter.current这种风格
}
|
带getter和setter的属性
在Java中,通常将字段声明为私有的,然后添加公有的getter和setter方法来提供访问字段的接口。像这样拥有一对getter/setter的字段,通常被称为属性(property)。
Scala对每个字段都提供了getter和setter方法。
在面向JVM的类中,这个简单的Person类有一个私有的age字段和相应的,公有的getter和setter方法。(如果将age声明为private的,getter和setter方法也是私有的。)Scala中,getter和setter分别叫做age和age_=。
|
println(fred.age)// 调用方法fred.age()
fred.age=21// 调用方法fred.age_=(21)
|
将这个简单的Person编译后,使用javap查看生成的字节码,可以验证这一点。
|
// -private选项说明显示所有的类和成员
javap-privatePerson.class
|
|
publicclassPerson implementsscala.ScalaObject{
privateintage;
publicintage();
publicvoidage_$eq(int);// =号被翻译成了$eq
publicPerson();
}
|
知道了这些默认实现后,就可以使用自己的实现来代替默认实现了。
|
classPerson{
privatevarprivateAge=0
defage=privateAge
defage_=(newValue:Int){
if(newValue>privateAge)privateAge=newValue
}
}
|
Scala中,字段和getter/setter间的关系,还有其他几种情况。
使用val声明的字段,是只有getter,因为val声明的是不可变的啊。Scala中不能实现只有setter的字段。
还有种对象私有字段。Scala中,方法可以访问该类的所有对象的私有字段,这一点与Java一样。如果通过private[this]来字段来修饰,那么这个字段是对象私有的,这种情况下,不会生成getter和setter。对象私有字段,只能由当前对象的方法访问,而该类的其他对象的方法是无法访问的。如果说分不清楚对象和类的区别,这里就又要犯浑了。
接下来是一种与private[this]相似的访问控制。Scala中可以使用private[class-name]来指定可以访问该字段的类,class-name必须是当前定义的类,或者是当前定义的类的外部类。这种情况会生成getter和setter方法。
Bean属性(L1)
使用 @BeanProperty注解来为字段生成符合JavaBeans规范的getter/setter方法。使用该注解后,将会生成4个方法:Scala的getter/setter和JavaBeans规范的getter/setter(如果是val声明,就没有setter部分了)。
|
importscala.reflect.BeanProperty
// 在Scala 2.10.0之后已被废弃
// 使用scala.beans.BeanProperty代替
classPerson{
@BeanPropertyvarname:String=_
}
|
构造器(Constructor)
在Scala中,有两种构造器,主构造器(primary constructor)和辅助构造器(auxiliary constructor)。
辅助构造器
首先来讨论辅助构造器,因为比主构造器更容易理解。辅助构造器与Java构造器很相似,但有两点不同:
- 名字是this(Java中构造器名称与类名相同)
- 辅助构造器必须以对已经定义的辅助构造器或主构造器的调用开始
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
classPerson{
privatevarname=""
privatevarage=0
defthis(name:String){
this()// 调用主构造器
this.name=name
}
defthis(name:String,age:Int){
this(name) // 调用辅助构造器
this.age=age
}
}
|
|
valp1=newPerson// 主构造器
valp2=newPerson("Fred") // 第一个辅助构造器
valp3=newPerson("Fred",42)// 第二个辅助构造器
|
主构造器
Scala中每个类都有主构造器,并且是与类定义混合在一起的。
主构造器的参数,是类名后()内的内容。
|
classPerson(valname:String,valage:Int){
// val name: String, val age: Int 部分就是主构造器的参数
}
|
主构造器的参数被编译成字段,其值被初始化成构造时传入的参数,可以为这些字段也加上访问控制。
主构造器会执行类定义中的所有语句。
|
classPerson{
println(0)
defprintNum(num:Int){println(num)}
println(1)
printNum(2)
}
|
定义如上一个简单类,然后创建一个Person的对象,结果如下:
|
scala>val fred=newPerson
0
1
2
fred:Person=Person@2c332d2a
|
也就是说,主构造器会将类定义内的,也就是{ }内的,所有语句执行一次。
如果主构造器参数不带val或var,那么会根据是否被方法使用来决定。如果不带val或var的参数被方法使用了,它会变为对象私有字段;如果没有被方法使用,则被当成一个普通的参数,不升级成字段。
主构造器或许不太好理解。Martin Odersky建议如此看主构造器:Scala中的类也接受参数,像方法一样。
可以将主构造器变为私有的,将private关键字放在圆括号前:
|
classPerson private(valid:Int){...}
|
嵌套类(L1)
在Scala中,几乎可以在任何的语法结构中内嵌任何语法结构。可以类中定义类,也可以在方法中定义方法。
Scala中每个实例都有自己的内部类。参考下面这段代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
importscala.collection.mutable.ArrayBuffer
classNetwork{
classMember(valname:String){
valcontacts=newArrayBuffer[Member]
}
privatevalmembers=newArrayBuffer[Member]
defjoin(name:String)={
valm=newMember(name)
member+=m
m
}
}
valchatter=newNetWork
valmyFace=newNetWork
|
chatter.Member类和myFace.Member类是不同的两个类。这一点与Java是不同的。
由于这一点特征,使得一些地方可能会碰见错误,这时候或许需要调整一下内部类。可以使用的方法有使用伴生对象或者使用类型投影(这里是将内部类中的Member换成NetWork#Member)。
与Java中一样,如果需要在内部类中使用外部类的引用,使用 外部类名.class的语法即可。不过Scala中有一个为这种情况服务的语法:
|
classNetwork(valname:String){outer=>
classMember(valname:String){
...
defdescription=name+" inside "+outer.name
}
}
|
本章习题解答。答案仅供参考,并不代表我的观点。
5.
|
importscala.reflect.BeanProperty
classPerson{
@BeanPropertyvarname:String=_
@BeanPropertyvarid:Long=_
}
|
生成的方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
Compiled from"Person.scala"
publicclassPerson implementsscala.ScalaObject{
privatejava.lang.Stringname;
privatelongid;
publicjava.lang.Stringname();
publicvoidname_$eq(java.lang.String);
publicvoidsetName(java.lang.String);
publiclongid();
publicvoidid_$eq(long);
publicvoidsetId(long);
publiclonggetId();
publicjava.lang.StringgetName();
publicPerson();
}
|
生成的JavaBeans方法当然应该是可以在Scala中调用的(不然有什么意义…)。不过个人不推荐在Scala中使用,这只是为了符合JavaBeans规范而已。
7.
|
classPerson(name:String){
valfirstName=name.split(" ")(0)
vallastName=name.split(" ")(1)
}
|
主构造参数到底是什么样的,推测是普通参数,因为并没有在任何方法中使用过。看字节码验证。
|
Compiled from"Person.scala"
publicclassPerson implementsscala.ScalaObject{
privatefinaljava.lang.StringfirstName;
privatefinaljava.lang.StringlastName;
publicjava.lang.StringfirstName();
publicjava.lang.StringlastName();
publicPerson(java.lang.String);
}
|
字节码中并没有出现name,所以如我所想,是普通参数。
8.
主构造器4个参数,并且有默认参数。
http://nerd-is.in/2013-08/scala-learning-classes/
相关推荐
快速掌握集合,Scala的集合有三大类:序列Seq、集Set、映射Map,所有的集合都扩展自Iterable特质 在Scala中集合有可变(mutable)和不可变(immutable)两种类型
scala-java-locales是JDK8上定义的java.util.Locale API和相关类的无尘室BSD许可实现,主要用于Scala.js。 它在Scala.js项目中启用了语言环境API,并支持要求语言环境(如数字和日期格式)的使用。 用法 只需将以...
Scala基本的OOP组件包括: class , trait , object class DemoClassAtrait DemoTraitAobject DemoObjectA Java之间的一些基本差异JavaScala类(仅非静态) 班级类(仅静态) 目的字段,方法,构造函数字段(var,...
运行这个: $ sbt consoleProject(fullClasspath in Runtime ).eval.foreach(println) 您将获得类路径列表。 检查任何版本不一致并在build.sbt强制使用正确的版本例如,如果您的 Scala 版本 2.10.3 和您的scala-...
在您的应用程序中有一个scala视图类树 您可以使用一些有用的预定义控件(例如选择,代码视图和图表) 以方便的方式使用链接数据(rdf数据),将html绑定到RDF属性(BananaRDF支持正在进行中) 文献资料 文档和示例...
修改“MainExample.scala”类编写您的 Spark 代码,然后使用以下命令编译项目: mvn clean package 在/target文件夹中,您将找到名为spark-scala-maven-project-0.0.1-SNAPSHOT-jar-with-depencencies.jar的结果...
它使用反射,因此如果您使用它,您可能需要将libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaV到您的项目中。 对象的枚举 定义 sealed abstract class Color ( red : Double , green : Double...
Scala-jdbc 一个小型库,可以更轻松地使用 JDBC 数据库。 亲: 小图书馆, 少量众所周知的依赖项(typesafe-config、commons-dbcp、scala-arm 和您选择的 JDBC 驱动程序), 对只想做Java/Scala 程序员来说非常...
类,您可以使用专门为此而构建的类,也可以提供您自己的类。 该库尝试尽可能轻量,以减少冷启动时间。 Circe 用于解析,但仅使用自定义编码器/解码器。 如果您愿意,可以随意为您的项目引入更多 Circe 库,但我们不...
Scala Maven模板模板 :backhand_index_pointing_right: Scala maven项目的骨架和常见的scala生态系统库的简单...pojo类(在语言之间使用) 职位:pojo:scala / java hello世界主类(在语言之间调用) scala: java:
scala json 解析库,源码 scala json master
启动和运行 docker run --rm -it -v /Users/ryo/ryo0/scala-chibicc/:/scala compilerbook cd /scala ./test.sh alias testscalacc="docker run ...这仅仅是因为您使用rax之类的64位兼容寄存器强制操作了32位(4字节)
使用surefire Maven插件为Java类运行Junit测试 增量编译a-la-sbt-保存Java / scala文件将重新触发测试。 去做: 添加用于Scala的测试框架(ScalaTest,Specs2,ScalaCheck) 用法: 首先运行Maven目标以解决...
test-memcached-sessions.zip,Jetty NoSQL Memcached和相关项目的测试用例。Jetty NoSQL Memcached的通用测试类。
它还负责 Scala 编译器的下载。 用法 获取 TSV 格式的 MNIST 数据集。 然后,运行以下命令: cd spark-mnist sbt package cd target/scala-2.10 spark-submit --name "Spark MNIST NN" --master [local|yarn-...
面向机器学习的Scala-第二版 这是发行的用于代码库 。 它包含从头到尾完成本书所必需的所有支持项目文件。 关于这本书 通过数据聚类和分类发现信息正在成为竞争性组织的关键差异因素。 机器学习应用无处不在,从自动...
该研讨会专门针对Scala 2开发人员,并假定您具有有关隐式,ADT和类型类的先验知识。研讨会前检出此存储库git clone git@github.com:bszwej/scala-3-crash-course.git 用sbt编译sbt compile 将其导入您喜欢的IDE中...
ScalaTSI Scala TSI可以从您的Scala类自动生成Typescript接口。安装要使用项目,请在project/plugins.sbt添加SBT插件依赖项: // See badge above for latest version numberaddSbtPlugin( " ...
这是Scala 2 Developers类Scala 3的存储库,包含教学材料和研讨会练习。 下载 要将此存储库下载到您的机器上,请确保您已安装 。 然后打开终端,将目录更改为要存储此存储库中包含的文件的任何位置,然后输入以下...
Scala-Slick-extras 方便收集常见类型的GetResult / Set Parameter实例(以及案例类的帮助器)。 非常适合我的项目,这些项目通常是argonaut和postgres的某种组合,因此您可能只想从中窃取而不是依赖于postgres驱动...