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