Private 私有变量
private 的作用不是表示这是我的代码,你不要碰。而是表示这个变量在这个类内是内部代码,外部代码不应使用。这个不是程序员间协作的问题,而是代码设计和架构的问题。甚至这个可能不是写给别人看的,而是今天的你写给下一个月的你看的。
而内部变量为啥不应修改,我应该不用说明了吧?于是我们自然而言地就需要一种方式去表达这种需求。在 OOP 的世界里,我们有 private。而在非 OOP 的世界里,你可能会看到用下划线打头的变量以表示内部变量。甚至巨离谱的你还会看到 "__private_skip_validation" 这种表示方式。
Getter/Setter
只要举一个例子就能说明其必要性。
如果你的变量可以被直接赋值,程序出问题时,你怎么从数十上百的外部调用中,找到哪个扑街偷偷地改了这个变量。特别是如果你的代码运行在多线程环境,同时又在处理几千几万个各式各样的请求。你该怎么追踪程序调用?而如果你有 setter,那你至少可以轻松地打一句log,设置个断点。
而 getter/setter 的核心就是代码可控。你可以清晰地知道你的变量何时何地被get/set,你可以轻松地修改/扩展其行为。
即使不是 OOP,你写 FP 或者面向过程的代码,也会有同样的需求。例如——bash。
明明可以直接 export ,为何要加个 setter 函数?
# https://github.com/sdkman/sdkman-cli/blob/HEAD/src/main/bash/sdkman-path-helpers.sh#L52-L57
function __sdkman_set_candidate_home() {
local candidate version upper_candidate
candidate="$1"
version="$2"
upper_candidate=$(echo "$candidate" | tr '[:lower:]' '[:upper:]')
export "${upper_candidate}_HOME"="${SDKMAN_CANDIDATES_DIR}/${candidate}/${version}"
}
Getter/Setter 带来的繁琐
这其实是另外一个问题。抽象地说,这是一个权衡问题。而被社会毒打地程序员们,都不约而同地选择,把麻烦留在编码时期,而不是以后哪天突然就为了一点小方便而暴雷。
于是为了解决手写 Getter/Setter 的繁琐,IDE 一般都支持自动生成 getter/setter。
支持多列编辑方便你改修饰符。
旧时代的 Java 有 Lombok (@Data),用于直接生成 getter/setter。
新时代 Java 提供了 Record 类(Java Language Updates)。
新的 OOP 语言 :
例如 Kotlin 提供了 Data 类,原生自带了 getter/setter
例如 Swift:
struct Rect {
var origin = Point()
var size = Size()
var center: Point {
get {
let centerX = origin.x + (size.width / 2)
let centerY = origin.y + (size.height / 2)
return Point(x: centerX, y: centerY)
}
set(newCenter) {
origin.x = newCenter.x - (size.width / 2)
origin.y = newCenter.y - (size.height / 2)
}
}
}
各个语言都不约而同地简化了 getter/setter 而不是去掉了 getter/setter ,甚至把变量的获取和赋值的底层实现替换为调用默认的 getter/setter ,而不是直接获取/赋值。足以说明这个 best practise 的需求有多坚实。
需要更多教程,微信扫码即可
👆👆👆
别忘了扫码领资料哦【高清Java学习路线图】
和【全套学习视频及配套资料】