封装
从数据的角度:封装 (encapsulation) 就是把抽象出的数据和对数据的操作封装在一起,数据被保护在内部,程序的其它部分只有通过被授权的操作(成员方法),才能对数据进行操作
从模块的角度:封装就是将需要重复使用的逻辑封装成共有的模块,提高开发效率,减少重复性编码
封装的理解和好处(以数据为例)
-
隐藏实现细节
-
既可以对数据进行验证,又保证数据的安全合理
如何体现封装(以数据为例)
- 通过成员方法实现对属性的封装,通过包实现对类的封装
封装的实现步骤(以数据为例)
-
将属性进行私有化
-
提供一个公共的
set
方法,用于对属性判断并赋值 -
Java 和 Scala 提供的访问权限修饰符
def setXxx(参数名 : 类型) : Unit = {
//加入数据验证的业务逻辑
属性 = 参数名
}
复制代码
- 提供一个公共的
get
方法,用于获取属性的值
def getXxx() [: 返回类型] = {
return 属性
}
复制代码
Scala 封装案例演示
创建一个员工类,对其必要属性进行私有化,并限制年龄只能为 [0,120]
object StuffDemo {
def main(args: Array[String]): Unit = {
val stuff = new Stuff(sex = 'M')
println(stuff) // Stuff(2000.0, 18, M)
stuff.setAge(24)
println(stuff) // Stuff(2000.0, 24, M)
stuff.setAge(190)
println(stuff) // Stuff(2000.0, 24, M)
}
}
/**
* 可以在主构造器中定义属性的默认值,甚至是设置属性的访问权限,但是失去了对属性的控制(解决方式是可以在调用构造方法前对设置的属性进行验证)
*
* @param salary
* @param age
* @param sex
*/
class Stuff(private var salary: Double = 2000, val sex: Char) {
private var age: Int = 18
def setAge(age: Int): Unit = {
if (age >= 0 && age <= 120) {
this.age = age
}
}
override def toString = s"Stuff($salary, $age, $sex)"
}
复制代码
细节
Scala
中为了简化代码的开发,在类中声明属性时,自动提供对应的setter/getter
方法(方法名为属性名_&eq/属性名
);如果属性访问权限声明为private
,对应setter/getter
方法的访问权限是private
;如果属性声明省略访问权限(编译器会自动为其加上public
访问权限),对应setter/getter
方法的访问权限是private
- 如果仅仅只是对一个属性进行简单的
set 和 get
,只需要声明该属性即可;访问属性直接使用对象.属性
即可(实质上是调用编译器自动生成的getter
方法);设置属性直接使用对象.属性=xxx
即可(实质上是调用编译器自动生成的setter
方法)