定义一个类


1 // 定义类,包含field及方法
2 scala> :paste
3 // Entering paste mode (ctrl-D to finish)
4 class HelloWorld {
5 private  var name = "leo"
6 def sayHello() {print("Hello, " + name)}
7 def getName = name
8 }
9 // Exiting paste mode, now interpreting.
10 defined class HelloWorld
11  // 创建类的对象,并调用其方法
12 scala> val helloWorld = new HelloWorld
13 helloWorld: HelloWorld = HelloWorld@380e4452
14 // 如果方法无参,可以不加括号,如果定义方法时不带括号,则调用方法时也不能带括号
15 scala> helloWorld.sayHello()
16 Hello, leo
17 scala> helloWorld.sayHello
18 Hello, leo
19 scala> helloWorld.getName
20 res9: String = leo
21 scala> helloWorld.getName()
22 :14: error: not enough arguments for method apply: (index: Int)Char  in  class StringOps.
23 Unspecified value parameter index.
24 helloWorld.getName()
25 ^

getter与setter

定义不带private的var field,此时scala生成的面向JVM的类时,会定义为private的name字段,并提供public的getter和setter方法。

而如果使用private修饰field,则生成的getter和setter也是private的。

如果定义val field,则只会生成getter方法。

如果不希望生成setter和getter方法,则将field声明为private[this]。

1 scala> class Student {
2  | var name = "leo"
3  | }
4 defined class Student
5 scala> val s = new Student
6 s: Student = Student@2a88981e
7 // 调用getter和setter方法,分别叫做name和name_=
8 scala> s.name
9 res0: String = leo
10 scala> s.name()
11 <console>:14: error: not enough arguments for method apply: (index: Int)Char in  class StringOps.
12 Unspecified value parameter index.
13 s.name()
14  ^
15 scala> s.name = "jack"
16 s.name: String = jack
17 scala> s.name
18 res2: String = jack
19 scala> s.name_ = "jen"
20 <console>:15: error: value name_ is  not a member of Student
21 val $ires1 = s.name_
22 ^
23 <console>:13: error: value name_ is  not a member of Student
24 s.name_ = "jen"
25 ^

自定义getter与setter

如果只是希望拥有简单的getter和setter方法,那么就按照Scala提供的语法规则,根据需求为field选择合适的修饰符就好:var、val、private、private[this]。

如果希望能够自己对getter与setter进行控制,则可以自定义getter与setter方法。

自定义setter方法的时候一定要注意Scala的语法限制,签名、=、参数间不能有空格。

1 scala> :paste
 2 // Entering paste mode (ctrl-D to finish)
 3class Student {
 4  private var myName = "leo"
 5  def name = "your name is " + myName
 6  def name_ = (newName:String) {
 7    print("you cannot edit your name!")
 8  }
 9}
10 // Exiting paste mode, now interpreting.
11 <console>:14: error: not found: value newName
12         def name_ = (newName:String) {
13                      ^
14 scala> :paste
15 // Entering paste mode (ctrl-D to finish)
16 class Student {
17  private var myName = "leo"
18  def name = "your name is " + myName
19  def name_=(newName:String) {
20    print("you cannot edit your name!")
21  }
22 }
23 // Exiting paste mode, now interpreting.
24 defined class Student
25 scala> val s = new Student
26 s: Student = Student@4fc8cd5c
27 scala> val s = new Student()
28 s: Student = Student@1dafc862
29 scala> s.name
30 res3: String = your name is leo
31scala> s.name = "leo1"
32you cannot edit your name!s.name: String = your name is leo

private[this]的使用

如果将field使用private来修饰,那么代表这个field是类私有的,在类的方法中,可以访问类的其他对象的private field。这种情况下,如果不希望field被其他对象访问到,那么可以使用private[this],意味着对象私有的field,只有本对象内可以访问到。

1 scala> :paste
2// Entering paste mode (ctrl-D to finish)
3 class Student {
4 private  var myAge = 0
5 def age_=(newAge:Int) {
6 if(newAge>0) myAge = newAge
7 else println("illegal age!")
8 }
9 def age = myAge
10 def older(s:Student) = {
11 myAge > s.myAge
12  }
13 }
14// Exiting paste mode, now interpreting.
15 defined class Student
16 scala> val s1 = new Student
17 s1: Student = Student@7ba9d3ec
18 scala> s1.age = 20
19 s1.age: Int = 20
20 scala> val s2 = new Student
21 s2: Student = Student@2dd6713
22 scala> s2.age = 25
23 s2.age: Int = 25
24 scala> s1.older(s2)
25 res8: Boolean = false

private[this]的使用,只有本对象内可以访问到。

辅助constructor

Scala中,可以给类定义多个辅助constructor,类似于Java中的构造函数重载,辅助constructor之间可以互相调用,而且必须第一行调用主constructor。

主constructor

Scala中,主constructor是与类名放在一起的,与Java不同,而且类中,没有定义在任何方法或者是代码块之中的代码,就是主constructor的代码,这点感觉没有Java那么清晰。

1 scala> class Student(val name:String, val age:Int) {
2 |   println("your name is " + name + ", your age is " + age)
3 | }
4 defined class Student
5 scala> val s = new Student
6 :14: error: not enough arguments for  constructor Student: (name: String, age: Int)Student.
7 Unspecified value parameters name, age.
8  val s = new Student
9 ^
10 scala> val s = new Student("leo", 30)
11 your name is leo, your age is  30
12 s: Student = Student@60cdee08

主construntor中还可以通过使用默认参数,来给参数默认的值。

如果主constructor传入的参数什么修饰都没有,比如name:String,那么如果类内部的方法使用到了,则会声明为private[this] name,否则没有该field,就只能被constructor代码使用而已。

内部类

Scala中,同样可以在类中定义内部类,但是与Java不同的是,每个外部类的对象的内部类,都是不同的类。

c2.Student类,c1.Student类,是不同的外部类的实例的不同的类。

object

object,相当于class的单个实例,通常在里面放一些静态的field或者method,第一次调用object的方法时,就会执行object的constructor,也就是object内部不在method中的代码,但是object不能定义接受参数的constructor。

object的constructor只会在其第一次被调用时执行一次,以后再次调用就不会再次执行constructor了。

object通常用于作为单例模式的实现,或者放class的静态成员,比如工具方法。

伴生对象

如果有一个class,还有一个与class同名的object,那么就称这个object是class的伴生对象,class是object的伴生类。伴生类和伴生对象必须存放在一个.scala文件之中,伴生类和伴生对象,最大的特点在于,互相可以访问private field。

object继承抽象类

object的功能和class类似,除了不能定义接收参数的constructor之外,object也可以继承抽象类,并覆盖抽象类中的方法。

apply方法

object中重要的一个特殊方法,apply方法,通常在伴生对象中实现apply方法,并在其中实现构造伴生类的对象的功能。而�