抽象和封装之间有什么区别?

可能重复:
抽象和封装之间的区别?

Java中的封装和抽象之间究竟有什么区别? 任何简短的例子也将不胜感激。

抽象和封装是两种口味很好的味道。

封装可以最大限度地减少您向代码用户公开的内容。 “用户”可能是您代码的其余部分,也可能是使用您发布的代码的任何人。

封装有一些明确的好处:

  • 代码的用户不依赖于程序中可能发生变化的部分。 当您更改程序时,他们不必更改其代码
  • 您可以更好地控制代码和状态在程序生命周期中的确切变化。 您必须处理更少的方案,并且需要修复的意外问题更少

我不懂Java,但这里有一个C#封装的小例子:

public class Giraffe { public Giraffe(int heightInFeet) { this.heightInFeet = heightInFeet; this.numberOfSpots = heightInFeet * 72; } public override string ToString() { return "Height: " + heightInFeet + " feet" + " Number of Spots: " + numberOfSpots; } private int heightInFeet; private int numberOfSpots; } 

它不是公开numberOfSpots ,而是封装在类中,并通过ToString方法公开。

抽象是使用扩展点让选择被推迟到运行精确代码的不同部分。 该选择可以在程序的其他地方,在另一个程序中进行,也可以在运行时动态进行。

抽象也有很大的好处:

  • 当您更改实现抽象的代码时,抽象的用户不必更改其代码。 只要抽象没有改变,用户就不必改变他们的代码。
  • 当您编写使用抽象的代码时,您可以编写一次代码,该代码可以重用于任何实现该抽象的新代码。 您可以编写更少的代码来完成更多工作。

C#中一个高度使用的抽象是IEnumerable 。 列表,数组,字典和任何其他类型的集合类都实现IEnumerableforeach循环结构和整个LINQ库都基于该抽象:

 public IEnumerable GetSomeCollection() { // This could return any type of int collection. Here it returns an array return new int[] { 5, 12, 7, 14, 2, 3, 7, 99 }; } IEnumerable someCollectionOfInts = GetSomeCollection(); IEnumerable itemsLessThanFive = from i in someCollectionOfInts where i < 5 select i.ToString(); foreach(string item in itemsLessThanFive) { Console.WriteLine(item); } 

您也可以轻松编写自己的抽象:

 public interface IAnimal { bool IsHealthy { get; } void Eat(IAnimal otherAnimal); } public class Lion : IAnimal { public Lion() { this.isHealthy = true; } public bool IsHealthy { get { return isHealthy; } } void Eat(IAnimal otherAnimal) { if(otherAnimal.IsHealthy && !(otherAnimal is SlimeMold)) { isHealthy = true; } else { isHealthy = false; } } private bool isHealthy; } IAnimal someAnimal = PullAnAnimalOutOfAWoodenCrate(); Console.WriteLine("The animal is healthy?: " + someAnimal.IsHealthy); 

你可以像在IAnimalIsHealthy一样使用IsHealthyIAnimal是一个abtraction,只有一个get访问器,而且IsHealthy上没有set访问IsHealthy是封装。

这两个概念完全不同。

抽象是使基类“抽象”然后扩展其function的实践。 抽象类是具体事物中不存在的东西; 它的唯一目的是扩展。 想想你是否在编写代表不同物种的课程。 你所有不同的物种都可以扩展一个抽象的动物类,因为它们都会像动物一样拥有共同的属性。 但是,你永远不会实例化一个动物对象,因为你在世界上看到的每一只动物都是松鼠,狗,或鱼……或某种基础的抽象动物类的具体实现。

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

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

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

封装是为了保护您的成员变量或方法免受外界影响。

抽象是具体实施的方式。 这是用户不知道要使用的实现。

封装是抽象的一部分。 抽象概念是创建表示另一个对象的对象之一。 通常,原始对象比抽象更复杂。 因此抽象是一种表示,通常作为记忆的辅助,用于术语/交流等。可以这样想:抽象艺术是其他东西的表现。 方向盘,换档和2/3踏板是汽车工作方式的抽象。

基本上,抽象允许您使用许多细节来表示复杂的东西,因为它更简单。 在我看来,这与认知科学中的“分块”有关。 我们无法将复杂的东西放在头脑中,所以我们通过抽象,然后使用抽象来简化。 设计模式是另一个很好的例子。 我们可以谈论命令,状态或战略模式等,而不是谈论细节。

封装是形成/创建抽象的一部分。 对象的界面越小,抽象就越容易。 您无需了解发动机和变速箱如何驾驶汽车,您只需要了解它们的抽象(换档和加速器)。 发动机和变速箱的细节被封装(进入界面)以创建抽象。

抽象需要封装,因为抽象不能处理所有真实细节和复杂性(否则它不是抽象)。 因此换档是变速箱的不完整表示(或模型),但其完整性足以供日常使用。 封装可以被认为是“隐藏细节”,这对于创建更简单的表示是必要的。

讨论“界面”的概念也很重要。 在大多数情况下,术语“接口”和“抽象”在这种情况下更不可互换。 界面是用户交易或交互的系统的一部分。 汽车的接口是方向盘,换档和踏板等。抽象产生一个界面。 您不直接处理发动机/变速箱,而是处理各自的接口。

封装的另一个原因是因为我们处理的是不完整的模型/抽象,我们不了解原始的完整复杂性,并且不能信任处理所有变量(因为我们不了解完整的模型)。 这对于解耦很重要,因为没有抽象,交互组件就会彼此了解太多。 想一想,因为每辆车都有方向盘,踏板和换档,你可以驾驶任何汽车,无论发动机类型如何等。此外,变速箱从发动机中抽出。 否则每个自定义引擎都需要一个自定义变速箱。

同样,Class是一种抽象。 该类通过其接口表示一些复杂的模型 – 该类的公共成员。 该接口是通过封装创建的。 该类为其协作者提供了更复杂实现的简化界面。 您也可以将其视为“需要了解”的情况。 该课程的合作者不需要确切知道它是如何工作的。 就像你不需要知道发动机如何驾驶汽车一样。

封装,接口和抽象在内聚和耦合以及代码维护方面起着至关重要的作用。 如果你没有创建好的抽象,并违反了“需要知道”的原则,那么你的代码就会变得纠结,脆弱,变成一场噩梦,因为没有“缓冲”。 “告诉不要问”的OO概念也与此有关。