Scala与Java差异(六)之类定义

一、类定义

(1)定义类,包含field以及方法

class ScalaClass {

  private var field = "one"

  def aMethod() { print("field : " + field ) }  

  def getField  = field 

}

(2)调用对象方法

val scalaClass = new ScalaClass

scalaClass.aMethod()

print(scalaClass.getField) // 也可以不加括号,如果定义方法时不带括号,则调用方法时也不能带括号

(3)getter与setter

1)var

此时scala生成的面向JVM的类时,会定义为private的name字段,并提供public的getter和setter方法。如:var field

2)val

只会生成getter方法。如:val field

3)private

生成的getter和setter也是private的,与java的私有属性变量类内访问一致。如:private var field

4)private[this]

不生成setter和getter方法,并且只是当前对象能够访问,与java的私有属性变量类内访问不一致。如:private[this] var field

5)自定义getter与setter方法

定义setter方法,def field_=(val: type){   },自定义setter方法的时候注意scala的语法限制,签名、=、参数间不能有空格

定义getter方法,def field=xxx

class Person{

  private var lastName = "mk"

  def name = lastName 

  def name_=(newVal: String)  {

    lastName=newVal

  }

}

val mk = new Person

print(mk.name)

mk.name = "xx"

// 调用getter和setter方法,分别叫做name和name_ =

6)Java风格的getter和setter方法

Scala的getter和setter方法的命名与java是不同的,是field和field_=的方式

让scala自动生成java风格的getter和setter方法,只要给field添加@BeanProperty注解即可

此时会生成4个方法,name: String、name_=(newValue: String): Unit、getName(): String、setName(newValue: String): Unit

import scala.reflect.BeanProperty

class Person{

  @BeanProperty var name: String = _

}

class Person(@BeanProperty var name: String)



val s = new Person

s.setName("MK")

s.getName()

7)辅助constructor

Scala中,可以给类定义多个辅助constructor,类似于java中的构造函数重载
辅助constructor之间可以互相调用,而且必须第一行调用主constructor

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

8)主constructor

Scala中,主constructor是与类名放在一起的,与java不同

而且类中没有定义在任何方法或者是代码块之中的代码,就是主constructor的代码,没有java构造方法清晰

class Person(val name: String, val age: Int) {

  println("name:" + name + ", age:" + age)

}

主constructor中还可以通过使用默认参数,来给参数默认的值

class Person(val name: String = "MK", val age: Int = 18) {

    println("name:" + name + ", age:" + age)

}

主constrcutor传入的参数什么修饰都没有,比如name: String,那么如果类内部的方法使用到了,则会声明为private[this] name;否则没有该field,就只能被constructor代码使用

 

二、对象object

object,相当于class的单个实例,在里面定义一些静态的field或者method(等价于java的定义静态变量和静态方法的类)

第一次调用object的方法时,就会执行object的constructor(即object内部不在method中的代码)。object不能定义接受参数的constructor

object通常用于作为单例模式的实现,或者放class的静态成员,比如工具方法

object Num {

  private val zero = 0

  println("init Number object!")

  def getZero = zero

}

(1) 伴生对象

有一个class,还有一个与class同名的object,那么就称这个object是class的伴生对象,class是object的伴生类
伴生类和伴生对象必须存放在一个.scala文件之中
伴生类和伴生对象,最大的特点就在于,互相可以访问private field

object Num {

  private val zero = 0

  println("init Number object!")

  def getZero = zero

}

class Num (val valueNum: Int) {
  def getValue = valueNum
}

(2)object继承抽象类

object的功能其实和class类似,除了不能定义接受参数的constructor之外,object也可以继承抽象类,并覆盖抽象类中的方法

abstract class Animal(var name: String) {
  def toStr(): String
}

object Cat extends Animal("cat") {
  override def toStr() = name
}

(3) apply方法

apply方法通常在伴生对象objec中实现apply方法实现构造伴生类的对象的功能。

而创建伴生类的对象时,一般不会使用new ClassName的方式,而是使用ClassName()的方式,隐式地调用伴生对象得apply方法,这样会让对象创建更加简洁

比如,Array类的伴生对象的apply方法就实现了接收可变数量的参数,并创建一个Array对象的功能

var arr = Array("a", "b")

class Cat(val name: String)
object Cat{
  def apply(name: String) = new Cat(name)
}

(4) main方法

在scala中要运行一个应用程序,那么必须有一个main方法,作为入口(像java中需要编写一个包含main方法类)

scala中的main方法必须在object中定义,格式为def main(args: Array[String])

object ScalaProgram {

  def main(args: Array[String]) {

    println("scala run...")

  }

}

除了实现main方法可以作为启动入口,继承App Trait类也可以作为启动入口,然后将需要在main方法中运行的代码,直接作为object的constructor代码;而且用args可以接受传入的参数

object ScalaProgram extends App {

   println("scala run ...")

}

运行上面的代码,需要将其放入ScalaProgram.scala文件,然后先使用scalac编译,再用scala执行

scalac ScalaProgram.scala

scala -Dscala.time ScalaProgram

App Trait的工作原理:App Trait继承自DelayedInit Trait,scalac命令进行编译时,会把继承App Trait的object的constructor代码都放到DelayedInit Trait的delayedInit方法中执行。

(5)object实现枚举

Scala没有直接提供类似于Java中的Enum类的枚举特性,如果要实现枚举,则需要用object继承Enumeration类,并且调用Value方法来初始化枚举值

通过Value传入枚举值的id和name,通过id和toString可以获取; 还可以通过id和name来查找枚举值。使用枚举object.values可以遍历枚举值

object Sex extends Enumeration {

  val MAN = Value(0, "man")
  val WOMAN = Value(1, "woman")

}

Sex(0)
Sex.withName("man")
for (s <- Sex.values) println(s)

 

posted @ 2021-03-24 22:04  茅坤宝骏氹  阅读(4)  评论(0)    收藏  举报  来源