Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如果封装没有隐藏数据,为什么称为数据隐藏?_Java_Oop_Encapsulation - Fatal编程技术网

Java 如果封装没有隐藏数据,为什么称为数据隐藏?

Java 如果封装没有隐藏数据,为什么称为数据隐藏?,java,oop,encapsulation,Java,Oop,Encapsulation,以下两个类在数据隐藏和封装方面有什么区别 在下面的示例中,我可以通过公开成员的值来访问该值 例:1 在下面的示例中,我可以使用getter方法访问member的值 例:2 class DataHiding { private int b; public DataHiding() { } public int getB() { return b; } public void setB(int b) {

以下两个类在数据隐藏和封装方面有什么区别

在下面的示例中,我可以通过公开成员的值来访问该值

例:1

在下面的示例中,我可以使用getter方法访问member的值

例:2

class DataHiding 
   {

    private int b;

    public DataHiding() {
    }

    public int getB() {
        return b;
    }

    public void setB(int b) {
        this.b = b;
    }

    }
在上述两个示例中,我都可以访问member的值。为什么称为数据隐藏封装?如果它没有隐藏数据


为什么Eg:1不被称为封装的?

如果要检索B的状态而不更改其值,会发生什么情况?您将创建getter而不是setter,您无法通过将B作为公共int访问来实现这一点

另外,在get和set两种方法中,如果我们有一个更复杂的对象,可能我们想要设置或获取对象的某些属性或状态

例如

private MyObject a;

public setMyObjectName(String name){
     MyObject.name = name;
}

public getMyObjectName(){
     return MyObject.name;
}
通过这种方式,我们通过限制对对象状态的访问来封装对象。

使用mutator和accessor隐藏逻辑,而不是方法的名称。它防止用户直接修改类成员

在第二个示例中,用户不知道类成员b,而在第一个示例中,用户直接暴露于该变量,可以更改它

想象一下这样一种情况:在设置b值之前,您想进行一些验证,或者使用一个helper变量和不想公开的方法。您将把逻辑封装在setter中,这样做可以确保用户在没有您监督的情况下无法修改变量。

在java中,所有方法都是虚拟的。这意味着,如果扩展某个类,可以重写方法的结果。例如,设想下一节课继续学习您的示例:

class DataHidingDouble extends DataHiding{
  public int getB(){
    return b*2;
  }
}
这意味着您在子类中保持对外部世界b的控制。 再想象一下某个子类,其中b的值来自非变量的东西,例如数据库。如果b是一个变量,那么如何让它返回值呢。 它隐藏数据,而不是值。因为类负责维护数据,并将正确的值返回给外部世界。

封装不是数据隐藏,而是信息隐藏。您正在隐藏内部结构和数据实现,以及数据访问逻辑

例如,如果愿意,您可以在内部将整数存储为字符串。在第一种情况下,更改该内部实现意味着您还必须更改依赖于b为int的所有代码。在第二种情况下,访问器方法将保护内部结构并为您提供int,如果内部结构发生更改,您不必更改代码的其余部分

访问器方法还使您有机会限制对数据的访问,除了普通的读写访问之外,还使其成为只读或写访问。更不用说可以验证进入对象的数据的完整性以及相应更改对象状态的其他逻辑了。

它是关于什么的 当您用面向对象编程和面向对象编程来标记这个问题时,我想您隐含着对JavaBean的思考。尽管如此,这是一个跨语言的常见问题,请阅读关于此问题的页面:

在编程语言中,封装是指两种语言之一 相关但不同的概念,有时与组合有关 其中:

一种语言机制,用于限制对某些对象的访问 组件。 一种便于捆绑的语言结构 使用方法或其他函数操作的数据 数据 一些编程语言研究人员和学者使用第一种语言 作为区别词单独或与第二个连用的意思 面向对象编程的特点,而其他编程 提供词汇闭包的语言将封装视为 与面向对象正交的语言特性

第二个定义的动机是在许多OOP中 组件的语言隐藏不是自动的,或者可以被覆盖; 因此,信息隐藏被定义为一个独立的概念 我更喜欢第二种定义

所以封装并不是隐藏数据或信息,而是将数据片段封装在Java中的一个类的语言组件中。JavaBeans封装数据

话虽如此,虽然封装是面向对象编程范式的主要特征之一,但在语言设计史上的某个时刻,它被认为不足以帮助设计更好的软件

历史 实现更好的软件设计的一个关键实践是,封装在这方面很有帮助。然而,大量的数据还不足以帮助实现这一目标,OOP先驱的其他努力当时是用不同的语言进行的,我相信SIMULA是最早引入其他概念的语言 我喜欢上课。然而,信息隐藏的思想在后面的文章中确实出现了,这些数据只与使用它来实现更大解耦的组件相关

但是回到话题上来

回答你的问题 在这种情况下,数据被封装并公开

这通常被称为全局变量,通常被认为是一种糟糕的编程实践,因为这可能会导致耦合和其他类型的错误

数据通过方法访问器进行封装和公开

这个类通常被称为JavaBean,如果它们被用于其他用途,那么它们是令人讨厌的

根据

2.1什么是豆子? 让我们从初始定义开始,然后对其进行细化:

“Java Bean是一种可重用的软件组件,可以在生成器工具中进行可视化操作。”

为什么现在它是一个令人憎恶的东西?由于人的原因,框架供应商通常会滥用它们。规范对此不够明确,但在这方面有一些声明:

因此,例如,将JDBC数据库访问API作为类库而不是bean提供是有意义的,因为JDBC本质上是一个编程API,而不是可以直接用于可视化操作的东西

我更愿意引用约书亚·布洛赫的话:

JavaBeans模式有严重的缺点约书亚·布洛赫,有效Java

相关点 如上所述,实现更好软件的一个关键实践是解耦。耦合是软件工程师最古老的战场之一。封装、信息隐藏与以下有助于解耦的实践有很大关系,原因有很多:

,违反此定律意味着代码具有耦合性。如果必须手动遍历整个数据图,则没有信息隐藏,图形的知识在组件之外,这意味着软件的可维护性和适应性较差。简而言之:重构是一个痛苦的过程。因此,他们被认为是一种反模式

某种程度上,允许人们不违反德墨忒尔定律的现代做法是

也就是说,你应该努力告诉对象你想要他们做什么;不要问他们关于他们的状态的问题,做出决定,然后告诉他们该做什么

,如果数据必须是公共的,那么它应该是不可变的。在某种程度上,如果不需要数据,一个模块可能会在另一个模块中引入副作用;如果单线程程序是这样的话,那么多线程软件就更痛苦了。今天,软件和硬件越来越多线程,线程必须通信,如果信息必须公开,它应该是不可变的。不变性保证了线程安全,不用担心。此外,必须保证整个对象图的不变性

class IsItImmutable {
  // skipping method accessors for brevity

  // OK  <= String is immutable
  private final String str;

  // NOK <= java.util.Date is mutable, even if reference is final a date can be modified
  private final Date  date;

  // NOK <= Set operations are still possible, so this set is mutable
  private final Set<String> strs;

  // NOK <= Set is immutable, set operations are not permitted, however Dates in the set are mutable
  private final Set<Date> udates = Collections.unmodifiableSet(...);

  // OK  <= Set is immutable, set operations are not permitted, String is immutable
  private final Set<String> ustrs = Collections.unmodifiableSet(...);
}

我同意你的回答,用户不知道类成员,但我的问题是它在哪里隐藏数据?我可以通过setter方法间接修改数据,这就是为什么称之为数据隐藏。这是正确的,更改内部实现意味着您还必须更改依赖于b的所有代码。但是我仍然可以使用setter方法修改信息,这样它就不会隐藏信息了。你把数据隐藏术语理解得太字面了。信息隐藏是一个更好的术语,更详细的描述应该是隐藏内部实现细节和保护数据和对象完整性。保持对象封装是可以的,我的问题是为什么它被称为数据/信息隐藏。我可以使用setter方法修改状态。乍一看,int类型没有多大意义,但是如果MyObject.name需要修剪字符串呢?通过这种方式,您可以控制对象的使用方式,从而隐藏真正的变量。请注意,在这两种方法中,我只揭示了如何获取或设置对象的名称,可能无法更改对象的另一个特征,这些特征是隐藏的。
class IsItImmutable {
  // skipping method accessors for brevity

  // OK  <= String is immutable
  private final String str;

  // NOK <= java.util.Date is mutable, even if reference is final a date can be modified
  private final Date  date;

  // NOK <= Set operations are still possible, so this set is mutable
  private final Set<String> strs;

  // NOK <= Set is immutable, set operations are not permitted, however Dates in the set are mutable
  private final Set<Date> udates = Collections.unmodifiableSet(...);

  // OK  <= Set is immutable, set operations are not permitted, String is immutable
  private final Set<String> ustrs = Collections.unmodifiableSet(...);
}