加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

7.Scala-类

发布时间:2020-12-16 18:02:25 所属栏目:安全 来源:网络整理
导读:第7章 类 7.1 简单类和无参方法 类的定义可以通过 class 关键字实现,如下: ? class Dog { private var leg: Int = _ def shout(msg: String) = { println(msg) } def currentLeg = leg} ? ? 使用这个类: val dog = new Dogdog shout "wangwang" println(d

第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
  }

}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读