7.Scala-类

第7章 类

7.1 简单类和无参方法

类的定义可以通过 class 关键字实现,如下:

class Dog {

  private var leg: Int = _

  def shout(msg: String) = {
    println(msg)
  }
  def currentLeg = leg
}

使用这个类:

val dog = new Dog
dog shout "wangwang"
println(dog currentLeg)
注:在 Scala 中,类并不声明为 Public,一个 Scala 源文件可以包含多个类。所有
这些类都具有公有可见性。调用无参方法时,可以加(),也可以不加;如果方法
定义中不带括号,那么调用时就不能带括号。

7.2 Getter、Setter 方法

对于 scala 类中的每一个属性,编译后,会有一个私有的字段和相应的
getter、setter 方法生成,比如: 
//getter
println(dog leg)

//setter
dog.leg_= (10)
println(dog currentLeg)

 当然,你可以不使用自动生成的方法,自己定义 getter 和 setter 方法

class Dog2 {
    private var _leg = 4
    def leg = _leg
    def leg_=(newLeg: Int){
        _leg = newLeg
    }
}

使用之:

val dog2 = new Dog2
dog2.leg_=(10)
println(dog2.leg)

尖叫提示:自己动手创建变量的 getter 和 setter 方法需要遵循以下原则:

1)字段属性名以 "_" 作为前缀,如:_leg

2)getter 方法定义为:def leg = _leg

3)setter 方法定义时,方法名为属性名去掉 前缀,并加上后缀发,后缀时:"leg_=",如例子所示

7.3 对象私有字段

package unit7

package society {
  package professional{
    class Executive {
      private[professional] var workDetails = null
      private[society] var friends = null
      private[this] var secrets = null
      
      def help(another: Executive) {
        println(another.workDetails)
        println(another.secrets) //报错访问不到
      }
    }   } }

7.4 Bean 属性

JavaBeans 规范定义了 Java 的属性是像 getXXX()和 setXXX()的方
法。许多 Java 工具都依赖这个命名习惯。为了 Java 的互操作性。将 Scala 字
段加@BeanProperty 时,这样的方法会自动生成。
 
1)创建一个 Bean,使用@BeanProperty 注解标识某个属性变量
import scala.beans.BeanProperty
class Person {
    @BeanProperty var name : String = _
}
 
2)通过 getMane、setName 访问属性
val fred = new Person
fred.setName("Fred")
fred.getName
println(fred.name)

尖叫提示: 

Person 将会生成四个方法:
1、name:String
2、name_=(newValue:String): Unit
3、getName():String
4、setName(newValue:String):Unit 
 

7.5 构造器

Scala 的类构造器分为主构造器和辅助构造器。 
 
1) 主构造器的参数直接放置在类名之后: 
定义类:
class ClassConstructor(var name: String, private var price: Double){
    def myPrintln = println(name + "," + price)
}

执行:
val classConstructor = new ClassConstructor("hello", 20.5)
ClassConstructor.myPrintln 
 
 
 
2) 主构造器会执行类定义中的所有语句: 
class ClassConstructor2(val name: String = "", val price: Double = 0){
    println(name + "," + price)
}

执行:
val ClassConstructor2 = new ClassConstructor2("aa", 20)
val ClassConstructor2_2 = new ClassConstructor2()
 
 
 
3) 通过 private 设置主构造器的私有属性: 
参考1)
 
 
 
4) 如果不带 val 和 var 的参数至少被一个方法使用,该参数将自动升级为字段,这时,name 和 price 就变成了类的不可变字段,
而且这两个字段是对象私有的,这类似于 private[this] val 字段的效果。
否则,该参数将不被保存为字段,即实例化该对象时传入的参数值,不会被保留在实例化后的对象之中。
 
 
 
主构造器参数 生成的字段/方法
name: String

对象私有字段。如果没有使用 name,

则没有该字段

private val/var name: String 私有字段,私有的 getting 和 setting 方法
var name: String 私有字段,公有的 getting 和 setting 方法
@BeanProperty val/var name: String 私有字段,公有的 Scala版和 Java版的 getting 和 setting 方法
如果想让主构造器变成私有的,可以在()之前加上 private,这样用户只能通过辅助构造器来造对象了
class ClassConstructor private (val name:String, val age:Int) {

  println(name, age)

}
 
5) 辅助构造器名称为 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
    }

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

7.6 嵌套类

即,在 class 中,再定义一个class,以此类推。

Java 中的内部类从属于外部类。Scala中内部类从属于实例。

1)创建一个嵌套类,模拟局域网的聊天场景

import scala.collection.mutable.ArrayBuffer
//嵌套类
class Network{
    class Member(val name: String){
        val contacts = new ArrayBuffer[Member]
    }

    private val members = new ArrayBuffer[Member]
    def join(name: String) = {
        val m = new Member(name)
        members += m
        m
    }
}

2)使用该嵌套类

//创建两个局域网
val network1 = new Network
val network2 = new Network

//nick 和 alice 加入局域网1
val nick = network1.join("Nick")
val alice = network1.join("Alice")

//jone 加入局域网2
val jone = network2.join("Jone")

//nick 和 alice 互相添加为好友
val nick = network1.join("Nick")
val alice = network1.join("Alice")

//nick.contacts += jone //这样不行,nick 和 jone 不属于同一个局域网,即, nick 和 jone 不是同一个 class Member 实例化出来的对象

在 Scala 中,每一个实例都有它自己的Menber类,就和他们有自己的 members 字段一样。也就是说,

network1.Member 和 network2.Member 是不同的两个类。也就是所谓的:

路径依赖类型,此处需要详细解释。

如果想让 members 接受所有实例的Member,一般有两种办法:

1)将 Member 作为Network 的伴生类对象存在

创建类:

import scala.collection.mutable.ArrayBuffer

class Network {


    val contacts = new ArrayBuffer[Network.Member]()


  //用于存放局域网中的对象
  val members = new ArrayBuffer[Network.Member]()

  def join(name: String) = {
    val m = new Network.Member(name)
    members += m
    m
  }

}


object Network{
  class Member(name: String){
    //用于存放某个Mem对象的联系人
    val contacts = new ArrayBuffer[Member]()
  }
}

2)使用类型投影,注意留意关键符号:"#"

创建类:

import scala.collection.mutable.ArrayBuffer

class Network {

  class Member(name: String){
    //用于存放某个Mem对象的联系人
    val contacts = new ArrayBuffer[Network#Member]()
  }

  //用于存放局域网中的对象
  val members = new ArrayBuffer[Network#Member]()

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

}
原文地址:https://www.cnblogs.com/LXL616/p/11123851.html