Questions tagged «encapsulation»

17
为什么有私有字段,保护不够?
private类字段/属性/属性的可见性有用吗?在OOP中,迟早要创建一个类的子类,在这种情况下,最好能够理解并能够完全修改实现。 当我对一个类进行子类化时,我要做的第一件事就是将一堆private方法更改为protected。但是,对外部世界隐藏细节很重要-因此我们需要protected而不仅仅是public。 我的问题是:您是否知道一个重要的用例,private而不是protected一个好的工具,或者两个选项“ protected&public”对于OOP语言是否足够?

15
为什么我们需要私有变量?
为什么在类中需要私有变量? 我读过的每本关于编程的书都说这是一个私有变量,这是您定义它的方式,但仅此而已。 在我看来,这些解释的措辞总是像我们对我们的职业确实存在信任危机。这些解释听起来总是像其他程序员要弄乱我们的代码一样。但是,有许多编程语言没有私有变量。 私有变量可以帮助防止什么? 您如何确定特定财产是否应为私有?如果默认情况下每个字段都应该是私有的,那么为什么在类中有公共数据成员呢? 在什么情况下应该公开变量?

15
TDD红绿色重构以及是否/如何测试变为私有的方法
据我了解,大多数人似乎都同意不应直接测试私有方法,而应通过任何公共方法对其进行测试。我可以理解他们的观点,但是当我尝试遵循“ TDD的三个定律”并使用“红色-绿色-重构”循环时,我对此有一些疑问。我认为最好用一个例子来解释: 现在,我需要一个程序,该程序可以读取文件(包含制表符分隔的数据)并过滤掉包含非数值数据的所有列。我想可能已经有一些简单的工具可以做到这一点,但是我决定从头开始实现它,主要是因为我认为这对我来说是一个不错的,干净的项目,可以进行TDD的实践。 因此,首先,我“戴上红色帽子”,也就是说,我需要测试失败。我想,我需要一种可以找到一行中所有非数字字段的方法。因此,我编写了一个简单的测试,当然它无法立即编译,因此我开始编写函数本身,并且在来回循环(红色/绿色)之后,我有了一个有效的函数和一个完整的测试。 接下来,我继续使用函数“ gatherNonNumericColumns”,一次读取文件,并在每一行调用我的“ findNonNumericFields”功能以收集最终必须删除的所有列。几个红绿色循环,我完成了,又一次具有工作功能和完整的测试。 现在,我认为我应该重构。由于我的方法“ findNonNumericFields”仅是因为我认为实现“ gatherNonNumericColumns”时需要它而设计的,所以在我看来,让“ findNonNumericFields”成为私有是合理的。但是,这将中断我的第一个测试,因为他们将无法再访问他们正在测试的方法。 因此,我最终得到了一个私有方法,以及一组测试它的测试。既然有很多人建议不要测试私有方法,那感觉就像我在这里陷入困境。但是我到底在哪里失败了? 我认为我本可以从更高的级别开始,编写一个测试以测试最终将成为我的公共方法的方法(即findAndFilterOutAllNonNumericalColumns),但这感觉与TDD的整个观点有些矛盾(至少根据Bob叔叔的说法) :您应该在编写测试和生产代码之间不断切换,并且在任何时间点,所有测试都在最后一分钟左右进行。因为如果我从为公共方法编写测试开始,那么在私有方法中获得所有详细信息之前,将需要几分钟(甚至几小时,甚至几天)才能使该方法测试公共方法通过。 那么该怎么办?TDD(具有快速的红绿色重构周期)是否与私有方法不兼容?还是我的设计有问题?

10
使用第三方库-始终使用包装器吗?
我参与的大多数项目都使用几个开源组件。作为一般原则,是否始终避免将代码的所有组件绑定到第三方库,而是通过封装包装器来避免更改的痛苦,是一个好主意吗? 例如,我们的大多数PHP项目都直接使用log4php作为日志记录框架,即通过\ Logger :: getLogger()实例化,它们使用-> info()或-> warn()方法,等等。在将来,但是,可能会出现一个假设的日志记录框架,该框架在某种程度上会更好。就目前而言,与log4php方法签名紧密相关的所有项目都必须在许多地方进行更改,以适应新的签名。显然,这将对代码库产生广泛的影响,任何更改都是潜在的问题。 对于这种情况下的面向未来的新代码库,我经常考虑(有时实现)包装器类来封装日志记录功能,并使其(尽管并非万无一失)更容易以最小的更改来改变日志记录的工作方式; 代码调用包装器,包装器将调用传递给日志框架du jour。 请记住,其他库中有更复杂的示例,我是否过度设计还是在大多数情况下是明智的预防措施? 编辑:更多考虑-使用依赖注入和测试加倍实际上要求我们无论如何都要抽象出大多数API(“我想检查我的代码是否执行并更新其状态,但不写日志注释/访问真实数据库”)。这不是决定者吗?

13
为什么“较低”的应用程序层不了解“较高”的层是一个好主意?
在典型的(设计良好的)MVC Web应用程序中,数据库不知道模型代码,模型代码不知道控制器代码,并且控制器代码不知道视图代码。(我想您甚至可以从硬件开始甚至更远的地方开始,而且模式可能相同。) 换个方向,您只能向下移动一层。视图可以知道控制器,但不能知道模型。控制器可以知道模型,但不能知道数据库;该模型可以识别数据库,但不能识别操作系统。(更深层次的内容可能无关紧要。) 我可以直观地理解为什么这是一个好主意,但我无法明确表达。为什么这种单向分层样式是个好主意?

8
在getter和setter里面应该允许什么?
我进入了有关getter和setter方法以及封装的有趣的Internet争论。有人说,他们应该做的只是分配(设置器)或变量访问(获取器),以使它们“纯净”并确保封装。 我是对的,这会完全破坏首先使用getter和setter的目的,应该允许进行验证和其他逻辑(当然没有奇怪的副作用)吗? 何时应进行验证? 设置值时,在设置器内部(以防止对象进入无效状态-我认为) 在设置值之前,在设置器之外 在对象内部,每次使用该值之前 是否允许设置器更改值(也许将有效值转换为某些规范的内部表示形式)?

5
为什么我们需要动态类型语言的枚举?
我在这里阅读一些代码,发现一个枚举用于存储html标签的名称。为什么我们需要这样做?使用此策略有什么好处? 我知道枚举在编译或静态类型的语言中有多么有用,但是当我看到动态类型的语言中的枚举时,我会感到好奇,就像上面显示的示例代码一样。因此,问题基本上可以归结为为什么我们需要使用动态类型语言的枚举,或者根本不需要它们?

10
您通常将对象或其成员变量发送到函数中吗?
这两种情况之间普遍接受的做法是: function insertIntoDatabase(Account account, Otherthing thing) { database.insertMethod(account.getId(), thing.getId(), thing.getSomeValue()); } 要么 function insertIntoDatabase(long accountId, long thingId, double someValue) { database.insertMethod(accountId, thingId, someValue); } 换句话说,通常是将整个对象传递给您,还是只传递所需的字段,这更好吗?


6
Java为什么将软件包访问设置为默认访问?
我之所以问这个问题,是因为我相信他们这样做是有充分的理由的,而且根据我到目前为止的行业经验,大多数人都没有正确使用它。但是,如果我的理论是正确的,那么我不确定为什么它们包含私有访问修饰符...? 我相信,如果正确使用默认访问权限,则可以在保持封装的同时增强可测试性。并且这也使私有访问修饰符变得多余。 通过将唯一的包用于需要隐藏在世界其他地方的方法,可以使用默认访问修饰符来提供相同的效果,并且在不影响可测试性的情况下做到这一点,因为测试文件夹中的包具有相同的功能。能够访问源文件夹中声明的所有默认方法。 我相信这就是Java将包访问权限用作“默认”的原因。但我不确定为什么它们还包括私有访问权,我确定有一个有效的用例...


4
为什么Java不使用某些类的封装?
我的问题与System.in和System.out类有关(可能还有其他类似标准库中的类)。这是为什么?在OOP中这不是不好的做法吗?它不应该被使用,如:System.getIn()和System.getOut()?我一直有这个问题,希望在这里能找到一个好的答案。


7
如果变量具有getter和setter,应该公开吗?
我有一个带有私有变量的类,该类具有该变量的getter和setter方法。为什么不将该变量公开? 我认为您唯一需要使用getter和setter的情况是,是否需要执行除set或get之外的其他操作。例: void my_class::set_variable(int x){ /* Some operation like updating a log */ this->variable = x; }

5
关联,聚合和组合的用途是什么?
我研究了很多关于封装的理论以及实现封装的三种技术,即关联,聚合和组合。 我发现的是: 封装形式 封装是一种将类中的字段设为私有并通过公共方法提供对字段的访问的技术。如果某个字段被声明为私有,那么该类之外的任何人都无法访问该字段,从而将这些字段隐藏在该类中。因此,封装也称为数据隐藏。 封装可以描述为一种保护性屏障,可以防止该代码和数据被该类外部定义的其他代码随机访问。通过接口严格控制对数据和代码的访问。 封装的主要好处是能够修改我们已实现的代码,而不会破坏其他使用我们代码的人的代码。通过此功能,封装使我们的代码具有可维护性,灵活性和可扩展性。 协会 关联是一种关系,其中所有对象都有其自己的生命周期,并且没有所有者。让我们以老师和学生为例。多个学生可以与一个老师联系,一个学生可以与多个老师联系,但是对象之间没有所有权,并且都有自己的生命周期。两者都可以独立创建和删除。 聚合 聚合是协会的一种特殊形式,其中所有对象都有其自己的生命周期,但是有所有权,子对象不能属于另一个父对象。让我们以一个系和一个老师为例。一个老师不能属于多个部门,但是如果我们删除该部门,则该教师对象不会被销毁。我们可以将其视为“具有”关系。 组成 组合还是聚集的一种特殊形式,我们可以称其为“死亡”关系。这是一种很强的聚合。子对象没有生命周期,如果删除父对象,则所有子对象也将被删除。让我们再次以房屋与房间之间的关系为例。房屋可以包含多个房间,但是没有一个房间的独立生活,任何房间都不能属于两个不同的房屋。如果我们删除房屋,房间将被自动删除。 问题是: 现在这些都是真实的例子。我正在寻找有关如何在实际的类代码中使用这些技术的描述。我的意思是,使用三种不同的封装技术有什么意义,如何实现这些技术以及如何选择适用的技术。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.