有效Java项目14:您可以’;t在不更改API的情况下更改表示
这是来自Joshua Bloch的《有效Java》- 第14项(或第三版中的第16项):在公共类中,使用访问器方法,而不是公共字段 //像这样堕落的职业不应该公开有效Java项目14:您可以’;t在不更改API的情况下更改表示,java,Java,这是来自Joshua Bloch的《有效Java》- 第14项(或第三版中的第16项):在公共类中,使用访问器方法,而不是公共字段 //像这样堕落的职业不应该公开 class Point { public double x; public double y; } 因为这些类的数据字段是直接访问的,所以这些类不会 不提供封装的好处(第13项) 如果不更改API,则无法更改表示形式 作者最后一句话是什么意思?此语句在同一项中使用多次。请建议 术语导出API或API应按照作者在本书中的建议进
class Point {
public double x;
public double y;
}
因为这些类的数据字段是直接访问的,所以这些类不会
不提供封装的好处(第13项)
如果不更改API,则无法更改表示形式
作者最后一句话是什么意思?此语句在同一项中使用多次。请建议
术语导出API或API应按照作者在本书中的建议进行解释
导出的API由可访问的API元素组成
在定义API的包之外
这意味着当您有公共字段时,您的字段(表示)就是API本身,当您更改字段时,API也会更改
如果您有私有字段的公共getter,您将可以自由地使用您拥有的私有字段,并且您的API(您的公共方法)可以保持原样 作者的意思是,在不更改API的情况下,您无法更改数据的存储方式以及数据的表示方式(如您使用的容器类型)。
例如,如果决定使用point类而不是double来表示
x
和y
,则需要更改类的所有使用者(更改类的API)。API由所有公共方法和成员组成
数据成员是表示(或实现)的一部分
因此,如果将数据成员公开,更改表示也会更改API
例如,如果使用公共getter而不是公共数据成员,则可以在不更改API的情况下更改表示形式
例如,以下是使用相同API的两种不同表示形式:
class Point {
private double x;
private double y;
public double getX () {return this.x;}
public double getY () {return this.y;}
}
class Point {
private InnerPoint p;
public double getX () {return p.x;}
public double getY () {return p.y;}
}
这只可能是因为数据成员是私有的(因此不是API的一部分)。您不能重命名字段或将其更改为
私有的
,以提供封装
使用此API的代码是使用point.x
而不是point.getX()
如果不更改API,则无法更改表示形式
在上下文中,如果您倾向于更改定义为此类的类的属性,则表示一旦共享。如果不改变现有的API定义,这是不可行的。例如:-
class Point {
public double x;
public double y;
// accessors
double getX() { return this.x; }
double getY() { return this.y; }
}
class Graph {
void draw(Point point) {
double x = point.x; // what if you decide this should be 0 if y is not 0?
}
相反,如果您在那里使用getX()
getter,那么您可以将该逻辑作为
double getX() {
if(p == 0) return 0;
return this.x
}
在图中的实现中没有任何更改。好吧,假设点类,这相当简单
class Point {
public double x;
public double y;
}
现在,基本上x和y是2d平面上点的表示。例如,如果决定使用它,将如下所示:
Point p;
p.x = 5;
p.y = 10;
由于x和y声明公共,因此,如果有一天您决定将点表示切换为2D平面上的半径和角度,例如
class Point {
public double r;
public double angle;
}
上面的代码也必须更改,这意味着使用Point对象的客户端必须重新编译它们的代码。因此,通过将x和y声明为public,您将自己限制为这些声明,现在它们是PointAPI的一部分
然而,更好的方法是将点的内部表示封装到私有点状态,并仅公开所需的功能:
class Point {
private double x;
private double y;
// Computes norm2 of the point
public double norm2() {
return Math.sqrt(x*x + y*y);
}
}
现在,使用Point类的用户将只能使用公共API,在这种情况下,norm
方法,方式类似于:
Point p;
// Init coordinates
double norm = p.norm();
最后,如果您想更改内部表示,则与前面的示例相反,您的更改不会影响客户端代码。您发布的类不是公共类。它的包裹是私人的。总的来说,你的问题不是很好clear@Xtreme好吧,OP只引用了书中那一部分的一半:)投了赞成票。但是这个类是包私有的。如果我发布API,它将不会被所有人访问。请提出建议。好吧,即使类是通道作用域,并且它的内部表示形式不会泄漏到外部,但这仍然会在同一个包中对代码施加紧密耦合,从而难以重用和重构。因此,无论类是公共的还是包作用域的,我上面的建议都是完整的。