首页 > 代码库 > Scala系列:类

Scala系列:类

简单类和无参方法:

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

使用:

1 val counter1 = new Counter // 或 new Counter()2     // 类定义方法是带了(),调用时可带,也可不带 3     counter1.increment4     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   @BeanProperty3   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     m10   }11 }

使用:

1     val chatter = new Network2     val myFace = new Network3     val fred = chatter.join("fred")4     val wilma = chatter.join("wilma")5     fred.contacts += wilma6     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 += m11     m12   }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 }

 

Scala系列:类