java - 通过代码了解OOP中的封装

标签 java oop encapsulation

为了理解封装的概念,我遇到了这样的定义:“将属性和方法组合在同一个实体中,以隐藏应隐藏的内容并使可见的内容可见”。

但实际上,我不确定以下哪个代码更适合OOP:

public class Square {

    //private attribute
    private int square;

    //public interface
    public int getSquare(int value) {
        this.square = value * value;
        return this.square;
    }
}


要么

public class Square {

    //private attribute
    private int square;

    //public interface
    public int getSquare(int value) {
        this.square = calculateSquare(value);
        return this.square;
    }

    //private implementation
    private int calculateSquare(int value) {
        return value * value;
    }
}

最佳答案

将属性和方法组合在同一实体中,以隐藏应隐藏的内容并使要显示的内容可见


这是一个潜在的误导性陈述。您不是任何人的hiding任何东西。它也不是关于方法或字段。不幸的是,这是几乎每个地方的措辞方式。

怎么样

在编写任何程序段时(无论是函数,类,模块还是库),我们都将正在处理的程序段视为我的代码,其他所有代码都视为我的客户端代码。现在假设所有客户端代码都是由其他人而不是您编写的。您只编写此代码。即使您是唯一负责整个项目的人,也请假设一下。

现在,客户端代码需要与我的代码进行交互。因此,我的代码应该很好并且可以与之交谈。封装的概念说,我将我的代码分为两部分,(1)应该烦扰客户代码,(2)不要烦扰客户代码。 OO实现封装的方法是使用诸如public和private之类的关键字。实现这一目标的非OO方法是使用命名约定,例如前划线。请记住,您没有隐藏,只是将其标记为none-of-your-business

为什么

那为什么要封装东西呢?应该如何将我的代码组织到公共和私人区域?当someone使用我的代码时,它们当然会使用整个内容,而不仅仅是公共内容,那么none-of-their-business为何私有呢?请注意,这里someonetheir之类的词可以指代您自己-但仅适用于另一段代码。

答案是易于测试和维护。一个完整的项目如果经过详尽的测试,将是一项艰巨的任务。因此,至少在完成编码后,您只需测试我的代码的公共方面。您不测试任何客户端代码,也不测试我的代码的任何私有方面。这样可以减少测试工作量,同时保留足够的覆盖范围。

另一个方面是可维护性。我的代码永远不会是完美的,它将需要修订。由于错误修复或功能增强,我的代码将需要修改。因此,当我的代码有新版本可用时,客户端代码会受到多少影响?无,如果更改是在私有区域中进行的。此外,在计划更改时,我们尝试将更改尽可能地限制在私有区域中。因此,从客户的角度来看,这种变化没有影响。我的代码公开方面的更改几乎总是需要更改客户端代码,而现在这需要进行测试。在规划我的代码的总体规划时,我们尝试最大化私有区域下的面积,并最小化公共区域下的面积。

和更多

封装的思想与抽象的思想联系在一起,而抽象的思想又与多态性联系在一起。这些都不是严格面向对象的。即使在非OO世界(例如C甚至是Assembly)中,这些也适用。实现这些目标的方式有所不同。即使这适用于计算机以外的事物。

例如,污水管理的过程是

封装在排水管的公共接口内。公众只为下水道而烦恼。处理,处置,回收与普通大众无关。因此,污水处理可被视为-

抽象实体-仅包含漏极的接口。不同的政府和公司以自己的方式执行此操作。现在,一个城市可能拥有永久性的污水管理系统,或者它可以定期-

交换提供商。在政府运作的五十年中,情况很糟糕,但是一旦他们与BigCorp Inc.签约,现在人们就可以自由呼吸。我们只是做了多态性。我们切换了实现,并保持公共接口不变。政府和BigCorp公司都使用相同的排水管,但是它们自己的处理设备被封装起来并且可以进行多态切换。

在你的代码中

在选择封装存储的两个代码中,该字段都设为私有。这是一个不错的方法,当然也是面向对象的方法。在这两个代码中,算法也都被封装-对客户端不可见。真好在第二个代码中,您继续进行操作,并以单独的非公开方法提取了该算法。这是值得称赞的方法,尽管显然做一些琐碎的事情是过大的。更好的OO仍然如此。

您在第二个代码中所做的甚至有一个名称:strategy pattern。即使在这里它是无用的(且过大),也可以用于假设您要处理非常大的数字(例如,计算它们的平方需要很长时间)的情况下。在这种情况下,可以使您的calculateSquare方法受到保护,拥有一个FastButApproxSquare extends Square类,并使用另一种算法覆盖calculateSquare方法,该算法可以更快地计算出近似值。这样,您可以进行多态。需要确切值的人将使用Square类。需要近似值的人将使用FastButApproxSquare类。

关于java - 通过代码了解OOP中的封装,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42981184/

相关文章:

java - 类似字典的数据结构。这是一个好习惯吗?

java - 如何通过 OOP 打印多个值而不用在 Java 中添加它们

c# - 可以在 <T> 中传递父类(super class)的子类吗?

java - 如何使包私有(private)类仅对其他包可见?

javascript - 用JavaScript封装,存在吗?

c# - 为了惰性访问,你如何在本地封装一个字段值?

java - 将嵌套列表元素设置并获取到单个列表中

java - 查询解析用户数据

java - 在 xpages 中用 java 构建 url

c# - 在派生的 C# 类中隐藏属性