mirror of
https://github.com/sjsdfg/effective-java-3rd-chinese.git
synced 2025-03-03 13:50:57 +08:00
Update 16. 在公共类中使用访问方法而不是公共属性.md
This commit is contained in:
parent
00e92f7f8d
commit
10ba3019d3
@ -1,6 +1,6 @@
|
||||
# 16. 在公共类中使用访问方法而不是公共属性
|
||||
|
||||
有时候,你可能会试图写一些退化的类([degenerate classes](https://stackoverflow.com/questions/6810982/what-is-a-degenerate-class)),除了集中实例属性之外别无用处:
|
||||
有时候,你可能会试图写一些退化的类([degenerate classes](https://stackoverflow.com/questions/6810982/what-is-a-degenerate-class)),除了集中实例属性之外别无用处:
|
||||
|
||||
```Java
|
||||
// Degenerate classes like this should not be public!
|
||||
@ -10,7 +10,7 @@ class Point {
|
||||
}
|
||||
```
|
||||
|
||||
由于这些类的数据属性可以直接被访问,因此这些类不提供封装的好处(条目 15)。 如果不更改 API,则无法更改其表示形式,无法强制执行不变量,并且在访问属性时无法执行辅助操作。 坚持面向对象的程序员觉得这样的类是厌恶的,应该被具有私有属性和公共访问方法的类(getter)所取代,而对于可变类来说,它们应该被替换为 setter 设值方法:
|
||||
由于这些类的数据属性可以直接被访问,因此这些类不提供封装的好处(条目 15)。 如果不更改 API,则无法更改其表示形式,无法强制执行不变量,并且在访问属性时无法执行辅助操作。 坚持面向对象的程序员觉得这样的类是厌恶的,应该被具有私有属性和公共访问方法的类(getter)所取代,而对于可变类来说,它们应该被替换为 setter 设值方法:
|
||||
|
||||
|
||||
```Java
|
||||
@ -35,13 +35,13 @@ class Point {
|
||||
}
|
||||
```
|
||||
|
||||
当然,对于公共类来说,坚持面向对象是正确的:**如果一个类在其包之外是可访问的,则提供访问方法来保留更改类内部表示的灵活性。** 如果一个公共类暴露其数据属性,那么以后更改其表示形式基本上没有可能,因为客户端代码可以散布在很多地方。
|
||||
当然,对于公共类来说,坚持面向对象是正确的:**如果一个类在其包之外是可访问的,则提供访问方法来保留更改类内部表示的灵活性。** 如果一个公共类暴露其数据属性,那么以后更改其表示形式基本上没有可能,因为客户端代码可以散布在很多地方。
|
||||
|
||||
但是,**如果一个类是包级私有的,或者是一个私有的内部类,那么暴露它的数据属性就没有什么本质上的错误——假设它们提供足够描述该类提供的抽象。** 在类定义和使用它的客户端代码中,这种方法比访问方法产生更少的视觉混乱。 虽然客户端代码绑定到类的内部表示,但是这些代码仅限于包含该类的包。 如果类的内部表示是可取的,可以在不触碰包外的任何代码的情况下进行更改。 在私有内部类的情况下,更改作用范围进一步限制在封闭类中。
|
||||
但是,**如果一个类是包级私有的,或者是一个私有的内部类,那么暴露它的数据属性就没有什么本质上的错误——假设它们提供足够描述该类提供的抽象。** 在类定义和使用它的客户端代码中,这种方法比访问方法产生更少的视觉混乱。 虽然客户端代码绑定到类的内部表示,但是这些代码仅限于包含该类的包。 如果类的内部表示是可取的,可以在不触碰包外的任何代码的情况下进行更改。 在私有内部类的情况下,更改作用范围进一步限制在封闭类中。
|
||||
|
||||
Java 平台类库中的几个类违反了公共类不应直接暴露属性的建议。 着名的例子包括 `java.awt` 包中的 `Point` 和 `Dimension` 类。 这些类别应该被视为警示性的示例,而不是模仿的例子。 如条目 67 所述,暴露 `Dimension` 的内部结构的决定是一个严重的性能问题,这个问题在今天仍然存在。
|
||||
Java 平台类库中的几个类违反了公共类不应直接暴露属性的建议。 着名的例子包括 `java.awt` 包中的 `Point` 和 `Dimension` 类。 这些类别应该被视为警示性的示例,而不是模仿的例子。 如条目 67 所述,暴露 `Dimension` 的内部结构的决定是一个严重的性能问题,这个问题在今天仍然存在。
|
||||
|
||||
虽然公共类直接暴露属性并不是一个好主意,但是如果属性是不可变的,那么危害就不那么大了。当一个属性是只读的时候,除了更改类的 API 外,你不能改变类的内部表示形式,也不能采取一些辅助的行为,但是可以加强不变性。例如,下面的例子中保证每个实例表示一个有效的时间:
|
||||
虽然公共类直接暴露属性并不是一个好主意,但是如果属性是不可变的,那么危害就不那么大了。当一个属性是只读的时候,除了更改类的 API 外,你不能改变类的内部表示形式,也不能采取一些辅助的行为,但是可以加强不变性。例如,下面的例子中保证每个实例表示一个有效的时间:
|
||||
|
||||
|
||||
```Java
|
||||
@ -66,7 +66,4 @@ public final class Time {
|
||||
}
|
||||
```
|
||||
|
||||
总之,公共类不应该暴露可变属性。 公共累暴露不可变属性的危害虽然仍然存在问题,但其危害较小。 然而,有时需要包级私有或私有内部类来暴露属性,无论此类是否是可变的。
|
||||
|
||||
|
||||
[1]:
|
||||
总之,公共类不应该暴露可变属性。 公共累暴露不可变属性的危害虽然仍然存在问题,但其危害较小。 然而,有时需要包级私有或私有内部类来暴露属性,无论此类是否是可变的。
|
||||
|
Loading…
Reference in New Issue
Block a user