【问题标题】:Clarity on encapsulation in javajava中封装的清晰性
【发布时间】:2015-05-16 13:04:57
【问题描述】:

我浏览了几个博客,从中得到了以下几点。 Encapsulation Blog

  1. 不要将字段公开,因为任何其他类都可以直接修改变量。
  2. 使用getter 和setter 来修改变量。
  3. 通过在 getter 和 setter 中包含验证,我们可以控制变量不会被直接修改。

我在这里有点困惑。

考虑Employee,它的字段是名称和地址。 OrganizationOrganization2 类将为员工变量赋值并打印相同的值。

public class Employee {

    public String name;
    public String address;

    public void printEmpDetails() {
        System.out.println("Employee name :" + name + ", Employee address :"
                + address);
    }
}

public class Organization {

    public static void main(String[] args) {
         System.out.println("Employee details of org");

         Employee emp = new Employee();  //New Instance variable created
         emp.name= "JOHN";
         emp.address = "JOHN ADDRESS";     

    }
}

public class Organization2 {

    public static void main(String[] args) {
         System.out.println("Employee details of org2");

         Employee emp = new Employee();  //New Instance variable created
         emp.name= "JAMES";
         emp.address = "JAMES ADDRESS";     

    }
}
  1. Organization 正在创建一个员工实例(将它自己的一组值分配给员工)
  2. 同样Organization2 也在创建一个员工实例(将它自己的一组值分配给员工)

问题: 因为这是两个不同的实例。这里如何违反封装?

【问题讨论】:

标签: java oop encapsulation


【解决方案1】:

Employee 类违反了封装。变量nameaddress 是公开的。应该将它们设为 private,并且应该为它们定义 getter 和 setter。

【讨论】:

    【解决方案2】:

    重点是不要将类内部暴露给外部。此规则需要为您的代码提供灵活性。

    在您的代码中,进入OrganizationOrganization2 类,您可以直接访问Employee 类字段。相反,建议为这两个变量声明 setter 和 getter。

    public class Employee {
    
       private String name;
       private String address;
    
       public String getName() {
         return this.name;
       }
    
       public String getAddress() {
         return this.address;
       }
    
       public void setName(String newName) {
         this.name = newName;
       }
    
       public void setAddress(String newAddress) {
        this.address = newAddress;
       }
    
    }
    

    注意,nameaddress 字段被声明为私有。

    例如,如果您重新设计了 Employee 类的内部结构,您将只需要重写 getter 和 setter。您的所有其余代码都不需要干预。

    如果您直接访问 nameaddress 字段,您将需要重写所有代码,您可以在其中访问这些变量,以防您更改这些变量名称,甚至使用其他数据源,而不是这些变量.


    更新№1

    在您的情况下,封装意味着您需要在此类中隐藏 Employee 类的实现。暴露变量名会暴露你的类的内部结构,并且所有与你的 Employee 类交互的代码都严格地绑定到你的 Employee 类结构。

    假设以下情况。您的客户现在要求您修改 Employee 类的内部结构。您应该只存储客户 ID(一个新的类字段),但应该从数据库中读取 nameaddress

    如果你有 getter 和 setter,你只需要重写 Employee 类的这些 getter 和 setter。您的外部代码不会注意到此更改。

    但如果您直接访问nameaddress,则需要更改OrganizationOrganization2 类中的代码。

    现在假设您有 300 个类,它们直接相互访问。


    更新№2

    当我不在时,您在聊天中的问题:

    谢谢 这是我对抽象和封装的不理解。以汽车本身为例 抽象 - 隐藏汽车功能的内部工作。说休息系统 - 汽车制造商告诉 - 如果你按下休息,它会停止(这里我们隐藏休息系统的工作原理) 封装 - 提供一个公共接口来访问休息。汽车用户应该使用该特定的公共界面来操作休息时间。作为制造商,我可以决定当用户应用中断时要实施什么逻辑,并且该逻辑将来可能会在不通知用户的情况下发生变化。

    我的回答:

    是的,制造商只提供公共接口(刹车踏板),驾驶员不必担心系统的内部机制。如果制造商决定更改机制,他需要保留公共接口(刹车踏板),并且可以更改机制的内部结构。司机不会注意到这种变化。同样的方法适用于编程类。如果你隐藏(封装)你的类的内部,你可以让你的应用程序更易于维护和灵活。

    【讨论】:

    • 谢谢..但是你能分享你对我的abobe cmets的看法吗?
    • @user724747 我已经更新了我的答案,请检查一下。如果有任何不清楚的地方,请随时提问。
    • @user724747 不是真的,它不是抽象。这是一种使您的应用程序组件松散耦合且更具可测试性的具体方法。由于您的组件彼此隔离,因此在不影响其余代码的情况下测试和替换它们会更加容易。
    • @user724747 也请看这篇文章:java.dzone.com/articles/why-encapsulation-matters
    • 谢谢 这是我对抽象和封装的不理解。以汽车本身为例 抽象 - 隐藏汽车功能的内部工作。说休息系统 - 汽车制造商告诉 - 如果你按下休息,它会停止(这里我们隐藏休息系统的工作原理) 封装 - 提供一个公共接口来访问休息。汽车用户应该使用该特定的公共界面来操作休息时间。作为制造商,我可以决定当用户应用中断时要实现什么逻辑,并且该逻辑将来可能会在不通知用户的情况下发生变化。
    【解决方案3】:

    封装的基本概念是隐藏实现。虽然您可以做同样的工作来公开字段,但您可以直接访问该类的实现。这就是为什么说它使用 getter,setter 方法的原因。

    但这一切都取决于你想要做什么。有时提供直接访问而不实现任何 getter、setter 方法可能会更好

    【讨论】:

      【解决方案4】:

      封装的重点不是要防止不同的实例相互影响,而是要明确区分哪个类拥有数据以及与之相关的逻辑应该在哪里。

      例如,假设您想向Employee 引入一个附加属性,其中包含他被重命名的次数。如果您将数据成员公开为public,则每个使用Employee 的组织类都需要记住更新这个新属性。

      但是,如果您的数据成员是私有的,并且其他类只能使用该类的方法来操作它们,您可以确保在类中封装这个逻辑:

      public class Employee {
      
          private String name;
          private int numRenames = 0;
      
          public String getName() {
              return name;
          }
      
          public in getNumRenames() {
              return numRenames;
          }
      
          public void setName(String name) {
              this.name = name;
              ++numRenames;
          }
      
          // rest of the class snipped
      }
      

      【讨论】:

        【解决方案5】:

        这听起来像是家庭作业。不过我心情不错,还是会帮你的:)

        不要将字段公开,因为任何其他类都可以直接修改变量。

        public class Employee {
        
        public String name;
        public String address;
        

        字段是public,所以它破坏了封装。

        【讨论】:

        • 更清楚我的问题。因为变量是公开的。我们可以为不影响其他实例的特定实例的变量赋值吗?
        • 实例级。那我们为什么要把它设为私有并提供 getter 和 setter 呢?
        猜你喜欢
        • 1970-01-01
        • 2016-11-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-05-29
        • 2011-03-20
        相关资源
        最近更新 更多