3. Scala类和对象

1. Scala中的Class

1.1 class的声明

与Java中类的不同点

  • 在scala中定义的class都是public的,不用声明为public。类中的成员变量不加其他修饰符的情况下也是默认为public的。
  • 在一个文件中可以存在和定义多个类,所有这些类都具有public性质
  • 定义的这个文件和文件中的类名可以不同
  • 在定义好一个类后,不能再定义一个同名class,但是可以定义同名的object

类的构造器
每个类都可以有主构造器,主构造器的参数直接放置在类名后面

  • 主构造器中的参数可以用var, val, private var/val, private[this] var/val 修饰,访问特性随修饰符;没有被修饰符修饰的情况下默认为private[this]

类中可以定义辅助构造器,3个要点

  • 辅助构造器的名称只能叫做this
  • 辅助构造器中的参数列表不能有修饰符
  • 辅助构造器的第一句代码必须是调用主构造器或者其他辅助构造器
1.2 类中的属性

定义属性,不管是什么类型,必须进行初始化。定义属性的几种方式如下:

  • val修饰
    可被外部访问,但只可读,不能修改。
  • var修饰
    可被外部访问和修改
  • private var/val修饰
    仅可被本类或同名的object访问或修改
  • private[this] var/val修饰
    仅可被本类访问或修改
1.3 类中的方法

修饰类的几种方式和属性一样,修饰效果也一样。
Scala方法参数的一个重要特征是它们都是val而不是var,所以在Scala的方法中不能对入参重新赋值,编译会报错。

object HelloWorld {
  def main(args: Array[String]): Unit = {
    val r1 = new Rational(3, 4)
    val r2 = new Rational(4, 5)
    println(r1 add r2)   // 31/20
    println(r1*r2)   // 3/5
    println(r1*3)    // 9/4

    val r3 = new Rational(6)
    println(r3)   // 6/1

    val r4 = new Rational(66, 42)
    println(r4)   // 11/7
  }
}

/**
 * 有理数类
 * @param n:代表分子
 * @param d:代表分母
 */
class Rational(n:Int, d:Int){
  // 对于一个分数,分母不能为0,可以通过require定义一个前置条件
  require(d!=0) // 如果是true正常返回,否则抛出异常IllegalArgumentException

  private val g = gcd(n.abs, d.abs)
  val numer:Int = n/g
  val denom:Int = d/g

  // 辅助构造方法
  def this(n:Int) = this(n, 1)

  // 重写toString方法
  override def toString: String = numer + "/" + denom

  // 有理数加法, 下面这种声明方式编译会报错:value d is not a member of Rational, value n is not.....
  // 原因是n和d没有修饰符修饰,默认是类私有的,所以that的n和d不能被访问,如果定义类的时候给n和d加上修饰符val,下面这个方法就可执行
  // def add(that:Rational) = new Rational(n*that.d + d*that.n, d*that.d)

  // 需要把 n和d 做成字段,才能访问
  def add(that:Rational) =
    new Rational(
       numer * that.denom + denom * that.numer
      ,denom * that.denom
    )

  // 有理数乘法(Scala中 + *等是合理的方法名)
  def *(that:Rational) =
    new Rational(
       numer*that.numer
      ,denom*that.denom
    )

  // 方法重载
  def *(a:Int) =
    new Rational(
       numer*a
      ,denom
    )

  // 为了将分数进行正规化(例如 66/42 --> 11/7), 定义一个找分子和分母最小公约数的方法
  private def gcd(a:Int, b:Int): Int =
    if (b==0) a else gcd(b, a%b)

}

2. Scala中的object

Scala中不允许有静态成员,对此类使用场景,Scala提供了单例对象。定义和类相像,但是class关键字换成object关键字。

object HelloWorld {
  def main(args: Array[String]): Unit = {
    val a1 = new A      // class A (对于类中可执行的方法,在创建对象的时候首先都会执行一遍,类似Java的静态代码块)
    val a2 = new A()    // class A
    val a3 = A          // object A (第一次创建的时候会打印,后面就不会了)
    val a4 = A
    println(a1)   // A@35851384
    println(a2)   // A@649d209a
    println(a3)   // A$@6adca536
    println(a4)   // A$@6adca536
    println(a1.func(4,12))  // 12
    println(a3.func(4,12))  // 16
    println(A.func(4,12))   // 16
  }
}
/**
 * 不带构造器的类
 */
class A{
  println("class A")
  def func(a:Int, b:Int):Int = if(a>=b) a else b
}
// 伴生对象
object A{
  println("object A")
  def func(a:Int, b:Int):Int = a+b
}
2.1 object中的类和方法
2.2 伴生对象

当单例对象跟某个类共用同一个名字时,就被称为这个类的伴生对象。必须在同一个源码文件中定义类和类的伴生对象,同时这个类又叫作这个单例对象的伴生类。
类和它的伴生对象可以互相访问对方的私有成员。
没有同名的伴生类的单例对象称为孤立对象。

2.3 APP特质
发布了8 篇原创文章 · 获赞 0 · 访问量 107

猜你喜欢

转载自blog.csdn.net/qq_42994084/article/details/102908832