Java中封装和抽象之间究竟有什么区别?任何简短的例子也将受到赞赏。
答案 0 :(得分:8)
抽取和包装是两种口味很好的口味。
封装正在最大限度地减少您向代码用户公开的内容。 “用户”可能是您代码的其余部分,也可能是使用您发布的代码的任何人。
封装有一些明确的好处:
我不懂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
。列表,数组,字典和任何其他类型的集合类都实现IEnumerable
。 foreach
循环结构和整个LINQ库都基于该抽象:
public IEnumerable<int> 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<int> someCollectionOfInts = GetSomeCollection();
IEnumerable<string> 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);
您可以像使用IAnimal
和IsHealthy
一样使用它们。 IAnimal
是一个缩写词,只有get
个访问者,set
上没有IsHealthy
个访问者是封装。
答案 1 :(得分:6)
这两个概念完全不同。
抽象是使基类“抽象”然后扩展其功能的做法。抽象类是具体事物中不存在的东西;它的唯一目的是扩展。想想你是否在编写代表不同物种的课程。你所有不同的物种都可以扩展一个抽象的动物类,因为它们都会像动物一样拥有共同的属性。但是,你永远不会实例化一个动物对象,因为你在世界上看到的每一只动物都是松鼠,狗,或鱼......或某种基础的抽象动物类的具体实现。
封装是将类变量设为私有,然后允许从get和set方法访问它们的做法。这样做的目的是分开访问数据的方式和实现方式。例如,如果您有一个有需求的变量,那么每次更改它时,它也会将第二个变量增加1,然后您将封装该功能;这样你的代码就更可靠了,因为你每次访问原始变量时都不必记住遵守该规则。
如果您需要特定的代码示例,我建议您只进行Google搜索,因为有很多可用的示例。这是两个:
http://www.tutorialspoint.com/java/java_abstraction.htm http://www.tutorialspoint.com/java/java_encapsulation.htm
答案 2 :(得分:4)
封装是为了保护您的成员变量或方法免受外界影响。
抽象是具体实施的方式。这是用户不知道要使用的实现。
答案 3 :(得分:3)
封装是抽象的一部分。抽象概念是创建表示另一个对象的对象之一。通常,原始对象比抽象更复杂。因此抽象是一种表示,通常作为记忆的辅助,用于术语/交流等。可以这样想:抽象艺术是其他东西的表现。方向盘,换档和2/3踏板是汽车工作方式的抽象。
基本上,抽象允许你用很多细节来表示复杂的东西,因为它更简单。在我看来,这与认知科学中的“分块”有关。我们无法将复杂的东西放在脑海中,所以我们通过抽象,然后使用抽象来简化。设计模式是另一个很好的例子。我们可以谈论命令,状态或战略模式等,而不是谈论细节。
封装是形成/创建抽象的一部分。对象的界面越小,抽象就越容易。您无需了解发动机和变速箱如何驾驶汽车,您只需要了解它们的抽象(换档和加速器)。发动机和变速箱的细节被封装(进入界面)以创建抽象。
抽象需要封装,因为抽象不能处理所有真实细节和复杂性(否则它不是抽象)。因此换档是变速箱的不完整表示(或模型),但其完整性足以供日常使用。封装可以被认为是“隐藏细节”,这对于创建更简单的表示是必要的。
讨论“界面”的概念也很重要。在大多数情况下,术语“接口”和“抽象”在这种情况下更不可互换。界面是用户交易或交互的系统的一部分。汽车的接口是方向盘,换档和踏板等。抽象产生一个界面。您不直接处理发动机/变速箱,而是处理各自的接口。
封装的另一个原因是因为我们处理的是不完整的模型/抽象,我们不了解原始的完整复杂性,并且无法信任处理所有变量(因为我们没有了解完整的模型)。这对于解耦很重要,因为没有抽象,交互组件就会彼此了解太多。想一想,因为每辆车都有方向盘,踏板和换档,你可以驾驶任何汽车,无论发动机类型如何等等。此外,变速箱从发动机中抽出。否则每个自定义引擎都需要一个自定义变速箱。
类似地,类是抽象。该类通过其接口表示一些复杂的模型 - 该类的公共成员。该接口是通过封装创建的。该类为其协作者提供了更复杂实现的简化界面。您也可以将其视为“需要了解”的情况。该课程的合作者不需要确切知道它是如何工作的。就像你不需要知道发动机如何驾驶汽车一样。
封装,接口和抽象在内聚和耦合以及代码维护方面发挥着关键作用。如果你没有创建好的抽象,并违反了“需要知道”的原则,那么你的代码就会变得纠结,脆弱,变成一场噩梦,因为没有“缓冲”。 “告诉不要问”的OO概念也与此有关。