首页 > 代码库 > 快学Scala(5)--类

快学Scala(5)--类

构造简单类:

class Counter {

  private var value = http://www.mamicode.com/0>

  

在主函数中调用类:

def main(args: Array[String]): Unit = {
  val myCounter = new Counter
  myCounter.increment
  println(myCounter.current)
}

  注:当调用无参方法时,可以写圆括号也可以不写;推荐对于改值器方法(即改变对象状态的方法)使用(),对于取值器方法(不会改变对象状态的方法)去掉()是个不错的选择,例如:

myCounter.increment()
println(myCounter.current)

  注:可以通过不带()的方式声明current来强制这种风格

def current = value  //类的使用者必须使用myCounter.current,不带圆括号

 

Scala中带getter和setter的属性

对于简单类Person来说:

class Person {
  var age = 0
}

默认getter和setter调用方法:

println(p.age)  //将调用方法p.age()
p.age = 20  //将调用p.age=(20)

也可以自定义getter和setter方法:

class Person {
  private var privateAge = 0

 //getter -> age def age = privateAge //setter -> age_= 注意age_和=之间不能有空格 def age_= (newValue : Int) { if(newValue > privateAge) privateAge = newValue } }

  

若对于某个属性只希望有getter方法,不希望有setter方法,但可以通过特定的其他方式被改变

class Counter {
  private var value = http://www.mamicode.com/0    >  def increment() { value +=1 }    
  def current = value     //声明中没有()
}

  总结:在实现属性时有四个选择

  1. var foo: Scala自动合成一个getter和一个setter

  2. val foo: Scala自动合成一个getter

  3. 由你来定义foo和foo_=方法

  4. 由你来定义foo方法

 

 对象私有字段:

private[this] var value = http://www.mamicode.com/0>

  类的方法只能访问到当前对象的value字段,而不能访问同一类型的其他对象的该字段,这种访问被称作对象私有的。

  注:对于类私有的字段,Scala生成私有的getter和setter方法;而对于对象私有的字段,Scala根本不会生成getter或setter方法

不过,private[类名]修饰符可以定义仅有指定类的方法可以访问给定的字段。这里的类名必须是当前定义的类,或者是包含该类的外部类

 

Bean属性:

@BeanProperty var name: String = _  //name属性值为null

  将会生成四个方法:

  1. name: String

  2. name_=(newValue: String): Unit

  3. getName(): String

  4. setName(newValue: String): Unit

 

辅助构造器:

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)  //第二个辅助构造函数

  

主构造函数:

class Person(val name: String, private var age: Int) {
  println("Just constructed another person")

  def description = name + " is " + age + " years old"
}

  如果类名之后没有参数,则该类具备一个无参主构造器。这样一个构造器仅仅是简单的执行类体中的所有语句而已。

  如果不带val或var的参数至少被一个方法所作用,它将被升格为字段,等同于private[this] val字段的效果

  否则,该参数将不被保存为字段,它仅仅是一个可以被主构造器中的代码访问的普通参数

如果使用 class Person private (val id: Int) { ... }, 则主构造器私有,类用户必须通过辅助构造器来构造Person对象

 

嵌套类:

class NetWork {
  class Member(val name: String) {
    val contacts = new ArrayBuffer[Member]
  }

  private val menbers = new ArrayBuffer[Member]

  def join(name: String) = {
    val m = new Member(name)
    menbers += m
    m
  }
}

  调用:

def main(args: Array[String]): Unit = {
  val chatter = new NetWork
  val myFace = new NetWork
  val fred = chatter.join("Fred")
  val wilma = chatter.join("Wilma")
  fred.contacts += wilma
  val barney = myFace.join("Barney")
  fred.contacts += barney  //不可以这样做--不能将一个myFace.Member添加到chatter.Member元素缓冲当中
}

  问题:每一个实例都有它自己的Member类,就和他们有自己的member字段一样,也就是说是两个类

  解决方法:  1. 伴生对象(第六章)

        2. 类型投影

class Network {
    class Member(val name: String) {
      val contacts = new ArrayBuffer[Network#Member]
    }
    ...
}

  

快学Scala(5)--类