概念之间的区别

9
我参加了一场Java程序员的面试。在问了一些个人问题之后,面试官问了我“什么是封装和抽象”。我很高兴能回答这个问题,我回答说,封装是隐藏对用户不必要知道的实现细节,而抽象则是向用户展示重要的细节。在我回答后的几秒钟内,面试官又有了另一个问题。向用户展示重要的细节,这意味着隐藏与实现详细信息无关的数据。对吗?
我回答说是的!
然后面试官提出了另一个问题。“那么抽象和封装之间有什么区别?根据你的回答,我认为两者没有区别。”
我当时很无语,手都僵住了,真是糟糕的一天。
如果有人问你这样的问题,你会如何回答呢?
6个回答

3
简单来说,封装就是把代码写在一起,并仅显示出想要展示的部分。对于Java而言,这意味着将方法定义为私有的,只能从同一个类中访问。这样做可以避免直接暴露实例变量或函数,因为用户与此无关。
抽象化是隐藏复杂性的概念。以计算机为例,它们已经被抽象成执行实际计算的处理器,其中涉及芯片和门等细节对于普通人来说很难理解。因此,这个概念被抽象到了计算机中。
在Java中,抽象化意味着隐藏用户的实现细节。这包括将类定义为抽象类或定义接口。用户所看到的仅仅是接口(一组功能或API)。他不需要知道内部实现细节,只需知道必须提供什么输入(参数)以及相应的输出(返回类型)即可。
更好地理解Java的例子,请参考问题。

1

什么是封装?

封装就是保护任何可能发生变化的东西。封装的理念是,如果某个功能在代码中被很好地封装,即只在一个地方维护,而不是分散在代码中,那么它就很容易更改。可以用Java中封装的简单示例来更好地解释这一点。我们都知道构造函数用于在Java中创建对象,并且构造函数可以接受参数。假设我们有一个类Loan,其中包含一个构造函数,然后在各种类中使用此构造函数创建了Loan实例。现在需求发生变化,您需要在贷款时还包括借款人的年龄。由于此代码未被很好地封装,即未被限制在一个地方,您需要在调用此构造函数的每个位置进行更改,即为一个更改,您需要修改多个文件,这样更容易出错且繁琐,虽然可以通过高级IDE的重构功能完成,但如果您只需要在一个地方进行更改,那么是否更好呢? 是的,如果我们将Loan创建逻辑封装在一个方法中,例如createLoan(),并且客户端代码调用此方法,此方法内部创建Loan对象。在这种情况下,您只需要修改此方法而不是所有客户端代码。

示例

class Loan{
private int duration;  //private variables examples of encapsulation
private String loan;
private String borrower;
private String salary;

//public constructor can break encapsulation instead use factory method
private Loan(int duration, String loan, String borrower, String salary){
    this.duration = duration;
    this.loan = loan;
    this.borrower = borrower;
    this.salary = salary;
}

//no argument consustructor omitted here
// create loan can encapsulate loan creation logic

public Loan createLoan(String loanType){

 //processing based on loan type and than returning loan object
  return loan;
}

}

在Java中的封装示例中,可以看到所有成员变量都被设置为私有的,这样它们就得到了良好的封装。您只能直接在该类内部更改或访问此变量。如果要允许外部世界访问这些变量,最好创建一个getter和setter,例如getLoan(),它允许您在返回贷款之前进行任何类型的验证、安全检查,这样可以完全控制您想要做的任何事情,并且单个客户端访问渠道是受控制和管理的。

什么是抽象?

抽象类是不完整的,您不能创建抽象类的实例。如果要使用它,需要通过扩展使其完整或具体化。如果一个类不包含任何抽象方法并且实现了从抽象类或接口继承的所有抽象方法,则称该类为具体类。顺便说一下,Java具有抽象类和抽象方法的概念,但是Java中的变量不能是抽象的。在Java中,常见的抽象类示例是ActionListener,它具有称为actionPerformed(ActionEvent ae)的抽象方法。当触发ActionEvent时(例如单击JButton时),将调用此方法。在Java中,通常使用匿名类实现抽象方法actionPerformed(ActionEvent ae)来将ActionListener附加到JButton上,如下例所示:

JButton  ok = new JButton("OK");
ok.addActionListener(new ActionListener(){

       public void  actionPerformed(ActionEvent ae){
           //code to handle event
       }
});

在Java中,接口是提供抽象的另一种方式。接口默认为抽象,并且仅包含公共静态、最终常量或抽象方法。一个非常常见的面试问题是,在哪里应该使用抽象类,在哪里应该使用Java接口。在我看来,了解这一点对于设计更好的Java应用程序非常重要。如果您只知道类应该具有哪些方法的名称(例如,对于服务器,它应该具有start()和stop()方法),则可以选择Java接口。但是我们不知道这些start和stop方法的确切工作方式。如果您在设计类时知道某些行为,并且这些行为将保持在所有子类中,则将其添加到抽象类中。像Runnable这样的接口是Java中抽象的很好的例子,它用于抽象多个线程执行的任务。

0

封装是将数据包装成单个单元。例如class

抽象化你理解得很好


不回答问题,访问修饰符与抽象化无关。-1 - user207421
@EJP privateprotected用于隐藏类的外部实现。不是吗? - AJ.
访问是一个比实现更好的术语,这就是封装。 - Aniket Thakur
@AJ。抽象化是将接口与实现分离的过程,与访问控制无关。例如,考虑Java接口,其中方法是公共的,但实现是独立的。 - user207421

0

抽象是将基类“抽象化”,然后扩展其功能的实践。抽象类是一种不存在于具体形式中的东西;它的唯一目的是被扩展。想象一下,如果您正在编写代表不同物种的类。所有不同的物种都可以扩展一个抽象的动物类,因为它们都共享动物的共同属性。但是,您永远不会实例化一个动物对象,因为您在世界上看到的每只动物都是松鼠、狗、鱼...或某种基本的、抽象的动物类的具体实现。

封装是将类变量设为私有,然后允许从get和set方法访问它们的实践。这样做的目的是分离数据访问和实现方式。例如,如果您有一些变量需要满足每次更改时也将第二个变量增加1的要求,那么您将封装该功能;这样您的代码更可靠,因为您不必记住每次访问原始变量时都遵守该规则。

如果您想要特定的代码示例,我建议您进行谷歌搜索,因为有很多这样的示例可用。以下是两个示例:

http://www.tutorialspoint.com/java/java_abstraction.htm http://www.tutorialspoint.com/java/java_encapsulation.htm

这段内容与编程有关,其中包含两个链接,分别是Java中的抽象和封装。请点击链接以获取更多信息。


0

我认为封装是实现数据抽象的一种方式。

封装意味着将数据和函数封装在一个单元中。

抽象是在进行封装后得到的结果。


0

来自这个答案

抽象 - 抽象是用于确定对象的外部视图应该是什么的概念/技术。只提供必需的接口。

封装 - 是将数据和相关函数绑定到一个单元中的过程。它促进了抽象和信息隐藏。允许在单元上应用成员访问等功能,以实现抽象和信息隐藏。


那不是“源代码”。那只是StackOverflow上另一个问题的相当糟糕的答案,没有得到任何投票。另一个答案有超过50个赞,并引用了真正的来源。为什么你要引用这个答案还是个谜。-1 - user207421
@EJP 我认为这会帮助OP用简单的语言搞清楚他的概念。 - Prasad
可能是这样,但这种引用方式很奇怪。你甚至没有链接答案,只有问题。 - user207421
@EJP 我不知道要链接答案。谢谢您的编辑。现在为什么要在这个时候投反对票? - Prasad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接