【问题标题】:Encapsulation and Abstraction differences with help of an example in java借助 java 中的示例,封装和抽象的区别
【发布时间】:2012-08-29 06:32:45
【问题描述】:

我知道我的问题将被提名为在发布后立即关闭,但让我告诉你,我一直在搜索该网站,以寻找一个用 Java 举例说明的明显差异。请不要急于结束问题。

我写了以下内容:

public class Bank {
public String name="XXX Bank";
private int noOfCust;

public int getNoOfCust() {
 return getNoOfCusts() + 2;
}
public void setNoOfCust(int noOfCust) {
if(noOfCust > 0)
{
this.noOfCust = noOfCust;
}
}

private int getNoOfCusts()
{
noOfCust = 100;
return noOfCust;
}
}

这里,'noOfCust 是被隐藏的数据'。我不是通过引入私有 getNoOfCusts() 来公开实现部分。所以我相信这是封装,因为我已经将所有细节都捆绑在一个类中,并且也隐藏了数据。

问题1:如果这种强封装?如果没有,我该如何改进它以进行强封装?

问题2:抽象意味着完全隐藏实现。那么我上面做的是抽象吗?

我出于沮丧而发布了这个问题,因为我已经向面试官解释了上述解释,他告诉我,这不是正确的意思。

P.S:请按照上面的例子回答。我不想要实时示例或假设。

【问题讨论】:

  • 为什么客户数量有两个getter?为什么其中之一更改值?
  • 只是指定我可以在我写的私有方法中实现我想要的任何逻辑。其实没必要,不过我放那个只是为了说明,以后可以改逻辑。
  • D@Nandkumar:忘记密码。我刚才写它是为了问这个问题。我知道它可以改进。我需要概念之间的明确区别

标签: java


【解决方案1】:

选择必要的属性并隐藏不需要的细节是Abstraction。例如考虑人。人有眼睛、眼睛颜色、皮肤颜色属性。但是如果他去银行,那么银行会做他的抽象并且不考虑这些人的属性,而是选择姓名、地址、电话号码。这是抽象。你误会了。

封装只是意味着将对象状态(属性)和行为(方法)绑定在一起。如果你在创建类,你就是在做封装。

来自wiki:在 C++、Object Pascal 或 Java 等面向对象的编程语言中,抽象的概念本身已成为一种声明性声明——使用关键字 virtual(在 C++ 中)或 abstract(在 Java 中)。在这样的声明之后,程序员有责任实现一个类来实例化声明的对象。

【讨论】:

  • 那么使用类实现封装,使用私有方法(隐藏实现)实现抽象?
  • 想要对我问的示例进行解释。 Dint想要任何实时示例。此外,您说隐藏不需要的细节是抽象。但是其他人的cmets让我觉得抽象是做一个通用的抽象方法,留给具体实现的东西。
  • 使方法和类抽象。创建您将公开它的接口。编辑了一个答案,希望对你有所帮助。
  • 抽象是指java中抽象类的使用吗?
  • IMO 取决于设计级别抽象和编码级别抽象。 Design level abstraction : choosing necessary Object propertiescoding level abstraction : usage of abstract classes and interfaces whenever necessary.
【解决方案2】:
  • encapsulation 背后的基本思想是在类定义之外隐藏object 的内部表示。这通常是为了保护类的内部并提供一种系统的方式来访问它们。

  • 此外,getter/setter 组合背后的想法是提供一种访问该类属性的受控方式。因此,对于类的每个 private 属性,您将拥有 public setter()getter() 方法。

考虑到这两个因素,您可以很好地了解为什么您的代码在封装方面存在问题。实现了这个概念的骨架类可能如下:

public class Bank{
    private int noOfCustomers;
    private String name;


    public String getName(){
        return this.name;
    }

    public void setName(String name){
        this.name = name;
    }

    public int getNoOfCustomers(){
        return this.noOfCustomers;
    }

    public void setNoOfCustomers(int noOfCustomers){
        this.noOfCustomers = noOfCustomers;
    }

    /**
    * This method is to illustrate that it is perfectly valid to have
    * multiple types of setter methods
    */
    public void setNoOfCustomers(String noOfCustomers){
        try{
            this.noOfCustomers = Integer.parseInt(noOfCustomers);
        }catch(Exception exe){
            //Handle exceptions
        }
    }
}

关于abstraction:您可以将其视为以简化的方式呈现某些东西的想法,这在使用方面易于理解或与情况更相关。以您的示例为例,您可以将Bank 视为abstraction,它既可以代表联邦银行,也可以代表州会员银行或任何与此相关的东西。您基本上会为这些表示中的每一个派生特定的类,将 Bank 作为父类。

如果你研究一下File在Java中代表什么,我认为你可以更好地了解abstraction。文件本身是文件和目录路径名的抽象表示。但是,如果您研究源代码,您会发现它包含几个与其设计相似的属性private

封装,因此可以被认为是您如何保护您的属性免受滥用和抽象,因此可以被认为是您为外部用户提供了多少简化。

【讨论】:

  • 首先,我在代码中所做的 impl'n 是否适合封装?其次,抽象与封装有何不同。可以用上面的例子解释一下吗?
  • @AnujBalan:更新了我的答案。希望这会有所帮助:)
【解决方案3】:

封装:好吧,也许吧。你有一个非常奇怪的实现,调用者看不到它。

抽象:我们需要知道你实际上想要做什么。当前接口看起来像一个整数值的 getter/setter。这不是很抽象(并且实现不是那样工作的,它会做其他事情)。对于抽象,执行的操作(或涉及的对象)需要捕获不仅与具体实现分离的东西,而且还适用于更广泛的东西(不同但仍然相似,因为它们可以被制作成属于同一个“抽象”)。你的例子可能只是太小了。

要尝试在示例的基础上进行构建,也许您有一段代码可以按企业规模对企业进行分类。将存在具有诸如客户数量、员工数量等属性的“业务”抽象。使用此抽象的代码同样适用于银行、药店和杂货店。

【讨论】:

  • 所以当有人说你如何在java中实现封装时,很容易说'类(绑定所有信息)','使用私有变量(数据隐藏和实现)'?
  • 作为第一个近似值,是的。我个人不会说带有 getter 和 setter 且其中没有逻辑的简单 bean 是封装的好例子。它们更像是一个花哨的结构。
  • 根据给出的解释,抽象意味着抛出一个通用的方法,这会让其他人不知道它是如何实现的,它可以由其他具有自己细节的类来实现?
  • 除了使用get/set之外,能否请您提供一个良好封装的ex。
  • 我认为 java.lang.String 是一个很好的封装。它使用 UTF-16 编码的数组来保存数据(但你不需要知道),它可以在各种二进制编码之间转换,确保它真正保存字符数据,它可以为字符执行各种功能数据,并且封装允许保证不变性。
【解决方案4】:

我相信你可能误解了封装和抽象。

用黑盒更清楚地解释了封装。内部可以随时更改,但公共接口保持不变。话虽如此,您的代码是部分封装的,因为您有一个带有公共 getter 和 setter 的私有 int(以及一个私有 getter,我认为这没有任何意义,但这取决于您)。但是,String name 是公开的,没有 getter 或 setter;看来您打算将其设为常量,在这种情况下,应将其声明为 public、static 和 final。

抽象是将一个想法简化为更一般的、开销较大的想法的概念。在 Java 中,可以通过提供一个实现来抽象类,该实现提供了一个通用的想法但缺乏细节,并且它不能被实例化。这是通过abstract修饰符实现的,当修改一个类时,表示抽象类不能被实例化;修改方法时(必须在抽象类中),修饰符表示必须在任何子类实现中定义抽象方法。

Java 中的抽象示例,其中抽象表明棒球是一个球:

public abstract class Ball {
    // this class cannot be instantiated
    public abstract double getRadius();

    public double getVolume() {
        return (4.0 / 3) * Math.PI * Math.pow(getRadius(), 3);
    }
}

public class Baseball extends Ball {
    // this class can be instantiated
    @Override
    public double getRadius() {
        return 3.0;
    }
}

【讨论】:

  • 我有名称的 getter 和 setter,但我不想用 4 行额外的行来填充页面。所以你说封装是暴露公共方法但逻辑可以随时更改并且隐藏
  • @Thilo 我重写了我对抽象的解释(重点是它在 Java 中的使用)并提供了一个示例。
【解决方案5】:

java 中的封装是通过对象和方法自动进行的。 你不需要照顾那个。 但是,如果您愿意,您可以使用不同的隐藏方式来增加您的复杂性。 因此,其他人将无法破译您的代码。 您可能会使用递归函数和复杂的方法,并添加不必要的代码。 强封装!!

【讨论】:

    猜你喜欢
    • 2013-02-17
    • 2014-09-21
    • 1970-01-01
    • 1970-01-01
    • 2017-11-01
    • 2012-08-11
    • 1970-01-01
    • 2018-11-04
    • 2012-05-24
    相关资源
    最近更新 更多