【问题标题】:Do both these classes support encapsulation and ...?这两个类都支持封装和...吗?
【发布时间】:2011-09-27 12:49:27
【问题描述】:
public class Normal {
   public string name;     // name is public

   public String getName() {
        return name ;
   }

   public  String setName(String newName) {
         name = newName ;
         return name ;
   }

   public static void main(String args[]) {
      Normal normal = new Normal();
      normal.setName("suhail gupta");
      System.out.println( "My name is : " + normal.getName() );    
  }
 } 

新课从这里开始

public class Different {
   private string name;         // name is private

   public String getName() {
        return name ;
   }

   public  String setName(String newName) {
         name = newName ;
         return name ; 
   }

   public static void main(String args[]) {
      Different different = new Different();
      different.setName("suhail gupta");
      System.out.println( "My name is : " + different.getName() );    
  }
 } 

第一个类有 name 声明为 public 和其他类有 name 声明 private 。这两个类都做同样的工作,但只有 name different 的访问说明符。现在,

我的问题是?

  • 这两个类都支持封装吗?如果他们这样做,为什么privatepublic 更受欢迎? (我在声明 name 时所做的工作与声明 private 所做的工作相同)
  • 哪个类更容易维护?
  • refactoring 期间,哪些类程序员会放心?
  • normal 类与 different 类有何不同?
  • 当他们说Unencapsulated means Unchangeable时,这里怎么一成不变?

【问题讨论】:

  • @Maxpm no ,我一直在努力寻找令我满意的答案。请参阅代码中的链接
  • @富兰克林这是一个 oop 问题,java 的几行并没有使它成为一个 java 问题
  • 那我就用 lolcode 来回答吧……那几行就不是 lolcode 的答案了……
  • @Franklin ok..试着回答一下

标签: java oop encapsulation


【解决方案1】:

在“Normal”中(没有什么“正常”的地方),这是完全合法的代码:

public static void main(String args[]) {
   Normal normal = new Normal();
   normal.name = "suhail gupta";
   System.out.println( "My name is : " + normal.name );    
}

您的界面现在包含一个名为nameString 值。用户希望能够使用 VarName.name 或 VarName.setName 语法来设置它。用户希望能够使用 VarName.name 或 VarName.getName 来检索它;

例如,这在“Normal”中是合法的:

public static void main(String args[]) {
   Normal normal = new Normal();
   normal.name = null;
   String name = normal.name;
   System.out.println( "My name is : " + name );
}

现在,也许你会想“那又怎样?”想象一下,如果将变量设置为 null 与实际打印(发生错误的地方)相隔 30 个文件。很难知道是谁搞砸了该变量的值。并且您没有什么可以防止用户搞砸。

现在,如果您已将 setName 实现为:

public String setName(String newName) {
   assert newName;
   name = newName ;
   return name ;
}

然后,错误发生在用户做错事时立即。用户试图将一个不允许为 null 的值设置为 null,因此出错。您有一个显示错误发生位置的调用堆栈,这更容易调试。

当然,这无济于事,因为“Normal”的用户不必必须使用setName。他们可以直接戳name

虽然它在技术上可能是封装,但就我而言,如果用户可以轻松而轻松地颠覆它,那么它不是封装。如果没有保护,就没有封装。


当他们说 Unencapsulated 意味着 Unchangeable 时,这里怎么是不可更改的?

好的,假设你给了我一个包含Normal 的库。我会以某种方式使用它。也许我有 Normal 实例分散在 50 个文件中。他们all直接通过name而不是访问者设置和获取名称。这是完全合法的,因为你做到了public

现在,无论出于何种原因,您都决定不想将名称存储在字符串中。也许您需要能够拥有名字和姓氏。所以,假设你的库的下一个版本有这个定义:

public class Normal
{
    public string firstName;
    public string lastName;

    public String getName()
    {
        return firstName + " " + lastName;
    }

    public  String setName(String newName)
    {
        //parse newName into a first and last name.
        ...
        firstName = newFirstName;
        lastName = newLastName;
        return getName();
    }
}

缺少什么? public String name; 那不再可用,因为您现在有了名字和姓氏。请注意,这两个访问器方法根本没有改变

当我升级到您的库的新版本时,您将刚刚破坏了我的所有代码。我不喜欢我的代码仅仅因为你决定改变你在课堂上存储数据的方式而被破坏。我现在再也不会使用你做的任何东西了,因为你甚至不能让你的界面从一个版本到下一个版本保持一致。

如果你只是把事情做好了,这一切都不会发生。

【讨论】:

    【解决方案2】:
    • getter 和 setter 的想法是允许开发人员执行其他必需的逻辑来派生类字段的值。因此,将类字段保留为公共允许在为该字段分配值之前跳过执行逻辑。

    • 第二个类更容易维护,因为可以确定 name 变量的值始终是通过 setter 设置的。

    • 同样,第二类更适合重构,因为它暴露的成员更少。

    • 如果您想象其他开发人员使用“普通”类,他可能会选择直接设置 name 的值,而不是使用 setter。因此,如果将来您决定更改“名称”变量的可见性,您将破坏其他人的代码。在这样一个简单的示例中,这并不重要,但是在编写重要代码时,这往往会成为问题,因为您不想通过更改变量的可见性来破坏其他开发人员的代码。因此未封装的代码是不可更改的。

    一般来说,更好的设计往往会暴露更少的活动部件。但除此之外,封装还减少了其他代码可以操作类内部的方式。

    【讨论】:

    • 如何确定name的值是通过first类中的setter设置的?这是一个 public 变量;任何人都可以设置。
    • 这正是我要表达的意思。第一类不是封装的好例子。
    【解决方案3】:
    1. Different 是一个比 Normal 更好的封装示例,尽管如此简单,好处并不明显。

    2. Different理论上更容易维护,因为如果你想改变name的内部表示,你可以不修改公共API。

    3. 与 #2 相同,原因相同。

    4. 虽然第一类允许用户直接修改name,但第二类让他们通过getName()setName()

    5. 如果某些东西没有被封装,那么你就会向世界展示所有细节。这即使不是不可能,也很难追溯更改,因为您将破坏任何使用它的现有代码。

    【讨论】:

      猜你喜欢
      • 2017-10-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-10
      • 2014-11-29
      • 2015-07-10
      • 1970-01-01
      相关资源
      最近更新 更多