包结构是否有任何 java 模式来证明默认可见性修饰符的存在?
Is there any java pattern for package structure that justify the existence of the default visibility modifier?
我理解 "how packages should be structured" 是非常基于意见的。但是 java 包含默认包可见性的规则,因此这意味着在创建 Java 时考虑了特定的原因或模式,即如何在面向对象的环境中使用 object 构建包导向原则。
我将使用汽车示例,从使用默认可见性的方法开始:
com.company.car.Startup#main (public)
com.company.car.engine.CoreEngine#rotate (default)
乍一看,所有方法在语义上都应该最初声明为默认值(在这种情况下,main()
除外,它是入口点,应该是 public)。
好的,现在Startup#main
需要在启动汽车时调用CoreEngine#rotate
方法。但我不想公开 rotate()
方法 public 当有人将 CoreEngine
用于内部目的以外的其他用途时(例如从外部远程控制设备调用 CoreEngine#turnEngineLightOn
车)。
但是...rotate()
方法有一个默认的可见性,它是受包限制的,它也不能从 main()
方法访问!
在这种情况下,我有几个选择:
- 转
CoreEngine#rotate
方法public靠duck typing
- 更改引擎包class
我在实践中了解到,这不是现实生活中的项目应该如何考虑包在项目设计中的作用。那么这是否意味着默认可见性在语义上实际上是无用的?这是语言失败还是有设计模式来处理解决此语义问题的项目结构?
这样的模式真的存在吗?如果是这样,是否记录在案?你能提供一些使用面向对象代码的真实例子吗?
尝试查看 Joshua Bloch 的Item 13 Minimize the accessibility of classes and members,有效Java。正如项目的标题所说,您的 classes 和方法的可访问性必须尽可能严格。
因此,如果您要创建一个 API,您可以对 class 不希望外部组件使用的实体和方法使用默认包可见性。
我认为不需要特定的模式,但需要一个好的设计过程。在您的示例中,我认为存在设计问题,即:您有两个 class 过于紧密耦合,Startup
和 CoreEngine
不在同一个包中。
正如你所说,你不能简单地将Startup
和CoreEngine
合并为一个class,因为你会违反Single responsibility principle。
我认为你应该修改你的用例并问问你自己什么操作必须对你的用户可用。通过这种方式,您可以定义哪些是 public 方法。恕我直言,你有三种可能性:
- 言归正传here;
- 尝试考虑使用inner classes;
- 让 classes 的整个图表保持不变,并为您的 API 用户提供真正 public class 的 javadoc ]es.
关于第2点。我建议在这个页面上有一个战利品:Nested Classes。如文章中所述,使用嵌套 classes 的令人信服的理由包括:
这是一种逻辑分组的方式 class
place:如果一个class只对另一个class有用,那么它就是
将它嵌入 class 并将两者放在一起是合乎逻辑的。嵌套
这样"helper classes"让他们的包裹更加精简
增加封装:考虑两个top-levelclasses,A和B,
其中 B 需要访问 A 的成员,否则将被声明
私人的。通过将 class B 隐藏在 class A 中,A 的成员可以是
声明为私有,B 可以访问它们。此外,B 本身可以是
与外界隔绝。
它可以使代码更具可读性和可维护性:嵌套小
classes within top-level classes 将代码放在更靠近它的地方
您认为像下面这样的解决方案可以解决您的问题吗?
// Class Car provides the public API to interact with a car, but
// it delegates the specific functionalies to its inner classes.
public class Car {
private Startup startup;
private CoreEngine core;
// ...
private class Startup {
// The class can access to 'core', then it can
// invoke rotate() method
public void main() { /* ... */ }
}
private class CoreEngine {
public void rotate() { /* ... */ }
}
}
Java 中缺少的是嵌套范围的可能性。在 Scala 和 Js 中你可以做到。
我理解 "how packages should be structured" 是非常基于意见的。但是 java 包含默认包可见性的规则,因此这意味着在创建 Java 时考虑了特定的原因或模式,即如何在面向对象的环境中使用 object 构建包导向原则。
我将使用汽车示例,从使用默认可见性的方法开始:
com.company.car.Startup#main (public)
com.company.car.engine.CoreEngine#rotate (default)
乍一看,所有方法在语义上都应该最初声明为默认值(在这种情况下,main()
除外,它是入口点,应该是 public)。
好的,现在Startup#main
需要在启动汽车时调用CoreEngine#rotate
方法。但我不想公开 rotate()
方法 public 当有人将 CoreEngine
用于内部目的以外的其他用途时(例如从外部远程控制设备调用 CoreEngine#turnEngineLightOn
车)。
但是...rotate()
方法有一个默认的可见性,它是受包限制的,它也不能从 main()
方法访问!
在这种情况下,我有几个选择:
- 转
CoreEngine#rotate
方法public靠duck typing - 更改引擎包class
我在实践中了解到,这不是现实生活中的项目应该如何考虑包在项目设计中的作用。那么这是否意味着默认可见性在语义上实际上是无用的?这是语言失败还是有设计模式来处理解决此语义问题的项目结构?
这样的模式真的存在吗?如果是这样,是否记录在案?你能提供一些使用面向对象代码的真实例子吗?
尝试查看 Joshua Bloch 的Item 13 Minimize the accessibility of classes and members,有效Java。正如项目的标题所说,您的 classes 和方法的可访问性必须尽可能严格。
因此,如果您要创建一个 API,您可以对 class 不希望外部组件使用的实体和方法使用默认包可见性。
我认为不需要特定的模式,但需要一个好的设计过程。在您的示例中,我认为存在设计问题,即:您有两个 class 过于紧密耦合,Startup
和 CoreEngine
不在同一个包中。
正如你所说,你不能简单地将Startup
和CoreEngine
合并为一个class,因为你会违反Single responsibility principle。
我认为你应该修改你的用例并问问你自己什么操作必须对你的用户可用。通过这种方式,您可以定义哪些是 public 方法。恕我直言,你有三种可能性:
- 言归正传here;
- 尝试考虑使用inner classes;
- 让 classes 的整个图表保持不变,并为您的 API 用户提供真正 public class 的 javadoc ]es.
关于第2点。我建议在这个页面上有一个战利品:Nested Classes。如文章中所述,使用嵌套 classes 的令人信服的理由包括:
这是一种逻辑分组的方式 class place:如果一个class只对另一个class有用,那么它就是 将它嵌入 class 并将两者放在一起是合乎逻辑的。嵌套 这样"helper classes"让他们的包裹更加精简
增加封装:考虑两个top-levelclasses,A和B, 其中 B 需要访问 A 的成员,否则将被声明 私人的。通过将 class B 隐藏在 class A 中,A 的成员可以是 声明为私有,B 可以访问它们。此外,B 本身可以是 与外界隔绝。
它可以使代码更具可读性和可维护性:嵌套小 classes within top-level classes 将代码放在更靠近它的地方
您认为像下面这样的解决方案可以解决您的问题吗?
// Class Car provides the public API to interact with a car, but
// it delegates the specific functionalies to its inner classes.
public class Car {
private Startup startup;
private CoreEngine core;
// ...
private class Startup {
// The class can access to 'core', then it can
// invoke rotate() method
public void main() { /* ... */ }
}
private class CoreEngine {
public void rotate() { /* ... */ }
}
}
Java 中缺少的是嵌套范围的可能性。在 Scala 和 Js 中你可以做到。