Scala快速入门-5-类定义

Posted by Yezhiwei on January 4, 2018

知识点

  • 每个类都有一个主构造器,这个构造器和类的定义“交织”在一起,它的参数直接成为类的字段,主构造器执行类体中所有的语句
  • 类中的字段自动带getter和setter方法
  • 用@BeanProperty注解生成JavaBean的getXxx/setXxx方法
  • 辅助构造器是可选的,它们都叫做this

类定义

  • 定义及使用
scala> class Counter {
     | private var value = 0
     | def increment() {value += 1}
     | def current() = value
     | }
defined class Counter

scala> val myCounter = new Counter
myCounter: Counter = Counter@396a0391

scala> myCounter.increment()

scala> println(myCounter.current)
1

scala> myCounter.increment()

scala> println(myCounter.current)
2

说明:

Scala源文件中可以包含多个类

调用无参数方法或创建无参数对象时,可以写圆括号,也可不写

约定,对于改值器方法(即改变对象状态的方法)用(),而对于取值器方法(不改变对象状态的方法)去掉()

  • Scala对每个字段都提供getter和setter方法,如下定义一个公有字段
scala> class Person {
     | var age = 0
     | }
defined class Person

Scala生成面向JVM的类时,其中有一个私有的age字段及相应的两个公有的getter和setter方法;

对于私有字段,getter和setter方法也是私有的;

在Scala中,getter和setter分别叫做age和age_= (注意下划线和等号间没有空格)

  • 重新定义getter和setter方法,如:年龄不能设置成比现在的更小
scala> class Person{
     | private var privateAge = 0
     | def age = privateAge
     | def age_= (newValue: Int) {
     | if (newValue > privateAge) privateAge = newValue
     | }
     | }
defined class Person

// 测试

scala> val fred = new Person
fred: Person = Person@718f1128

scala> fred.age = 30
fred.age: Int = 30

scala> fred.age
res0: Int = 30

scala> fred.age = 21
fred.age: Int = 30

scala> fred.age
res1: Int = 30
  • 如何控制Scala对每个字段生成getter和setter的方法?

如果字段是私有的,则getter和setter方法也是私有的

如果字段是val, 则只生成getter方法

如果不需要任何getter和setter,将字段声明为private[this]即可

  • 用@BeanProperty注解生成JavaBean的getXxx/setXxx方法
scala> import scala.reflect.BeanProperty
import scala.reflect.BeanProperty

scala> class Person{
     | @BeanProperty var name: String = _
     | }
defined class Person

将会生成四个方法:

  1. name: String

  2. name_=(new Value: String): Unit

  3. getName(): String

  4. setName(newValue: String): Unit

  • 如果以主构造器参数的方式定义字段,并且需要JavaBeans版本的getter和setter方法,可以在构造器参数上加注解即可
class Person (@BeanProperty val name: String)

构造器

主构造器

  • 在Scala中,每个类都有主构造器。与类定义交织在一起。
  • 如果类名之后没有参数,则该类具备一个无参数主构造器。
  • 如果有参数,则把参数直接放置在类名之后。主构造器的参数被编译成字段,其值被初始化成构造时传入的参数。
  • 主构造器会执行类定义中的所有语句。
class Person(val name: String, val age: Int) {

	// 在定义对象时,println语句是主构造器的一部分,会被执行
	println("Just constructed person")
	
	def desc = name + " is " + age + " years old."
}
  • 可以通过在主构造器中使用默认参数来避免过多地使用辅助构造器。
  • 如果想让主构造器成为私有的,可以在参数列表前放置private关键字。
// Scala
class Person(val name: String, val age: Int) {

}

// 以上代码相当于Java的以下代码
public class Person {
	private String name;
	private int age;
	
	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}
	
	// getter and setter
	...
}

辅助构造器

  • 除了主构造器外,可以定义任意多的辅助构造器
  • 辅助构造器的名称为this。
  • 每一个辅助构造器都必须以一个对先前已经定义的其他辅助构造器或主构造器的调用开始。
class Person {
	private var name = ""
	private var age = 0
	
	def this(name: String) {
		// 调用主构造器
		this()
		this.name = name
	} 
	
	def this(name: String, age: Int) {
		// 调用前一个辅助构造器
		this(name)
		this.age = age
	}
}


// 可以以三种方式构造对象:
// 主构造器
val p1 = new Person
// 第一个辅助构造器
val p2 = new Person("Fred")
// 第二个辅助构造器
val p3 = new Person("Fred", 42)

敬请期待下一篇~