Spark开发指南

class

简单类和无参方法:

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

  使用:

1     val counter1 = new Counter // 或 new Counter()
2     // 类定义方法是带了(),调用时可带,也可不带
3     counter1.increment
4     counter1.increment()
5     println(counter1.current)
6     println(counter1.current()) // error:

  类定义方法时没带(),调用时也不能带

  推荐的风格是:改值的方法带();取值的方法不带(),定义时不带便可强制取值风格。

Setter和Getter

1 class Person {
2   var age = 0;
3 }

  对于属性age隐式的生成了age()和age_=(age: Int)方法。

  如果属性带private,则生成的方法也带private;如果属性不带private,则生成的方法为public。

  如果属性为val,则只生成get方法。

  如果禁用生成隐式的方法,使用private[this]声明。这样只能访问实例自身的属性,不能访问其它实例的属性,即对象私有成员。

  注:不能实现只有Setter,没有Getter的属性。想实现,只能用其它名称了。

  显式定义age()和age_=(age: Int)方法:

1 class Person {
2   private var _age = 0; // 变成私有并改名
3
4   def age = this._age;
5   def age_=(_age: Int) {
6     this._age = _age;
7   }
8 }

  生成的java代码实际上生成了四个方法:显式定义的两个,改名后变量隐式生成的(private)

  为什么要改名?不改名无法区分方法名和属性名,而且出现方法定义两次错误

Java Bean规范

  生成类似Java Bean的setAge和getAge方法,只需要添加一个注解:@BeanProperty

1 class Person {
2   @BeanProperty
3   var age = 0;
4 }

  上面的例子除了隐式生成了age()和age_=(age:Int)方法外,另外生成Java Bean风格的getAge()和setAge(age:Int)方法

主构造方法:

  和类定义交织在一起:

  • 参数被编译成字体;
  • 主构造方法会执行类定义中的所有语句;
  • 构造方法中参数不带val也不带var,只有被一个以上方法调用时才会提升为字段。类似于private[this] val效果
1 class Person(@BeanProperty var age: Int) {
2 }

会生成一个带age:Int参数的构造函数;

  • age()和age_=(age:Int)方法
  • getAge()和setAge(age:Int)方法

一个类如果没有显式定义主构造方法,会隐式生成一个无参不做任何操作的主构造方法。

辅助构造方法:

辅助构造方法的名称为this;

辅助构造方法每一行必须是调用构造方法(主构造方法或其它辅助构造方法)

def this(age:Int) {
  this()
  _age = age
}

嵌套类:

内部类与外部类实例相关联

1 class Network {
 2   class Member(val name: String) {
 3     val contacts = new ArrayBuffer[Member]
 4   }
 5   private val members = new ArrayBuffer[Member]
 6   def join(name: String) = {
 7     val m = new Member(name)
 8     members += m
 9     m
10   }
11 }

使用:

1     val chatter = new Network
2     val myFace = new Network
3     val fred = chatter.join("fred")
4     val wilma = chatter.join("wilma")
5     fred.contacts += wilma
6     val ngy = myFace.join("hongdao");
7     fred.contacts += ngy; // error

解析:

  val fred和wilma的类型为chatter.Member;ngy的类型为myFace.Memeber;fred.contacts的实际类型为ArrayBuffer[chatter.Member];   所以fred.contacts可以添加wilma,不可以添加ngy。

如果不希望这个效果,可以使用两种方式:

方式一:伴生对象

1 class Network {
 2   private val members = new ArrayBuffer[Network.Member]
 3   def join(name: String) = {
 4     val m = new Network.Member(name)
 5     members += m
 6     m
 7   }
 8 }
 9 object Network {
10   class Member(val name: String) {
11     val contacts = new ArrayBuffer[Member]
12   }
13 }

方式二:类型投影 Network#Member

任何Network的Member

 1 import scala.collection.mutable.ArrayBuffer
 2
 3 class Network {
 4   class Member(val name: String) {
 5     val contacts = new ArrayBuffer[Network#Member]
 6   }
 7   private val members = new ArrayBuffer[Network#Member]
 8   def join(name: String) = {
 9     val m = new Member(name)
10     members += m
11     m
12   }
13 }

内部类访问外部实例:

  • 外部类.this
  • 外部类实例别名
1 class Network(val name: String) { outter => //外部类实例别名
2   class Member(val name: String) {
3     val contacts = new ArrayBuffer[Network#Member]
4     def out = println(Network.this.name)
5     def out2 = println(outter.name)
6   }
7 }