理解封装和抽象的简单方法
学习面向对象的概念特别有兴趣深入理解抽象和封装。
已经检查了下面
抽象VS信息隐藏VS封装
抽象和封装之间的区别?
我发现很难用真正简单的示例类/代码段来理解这些概念。
我的一位同事说,抽象只不过是创build抽象类和保护其成员variables的普通类,其范围称为封装(Encapsulation)。
有一个简单的方法,我可以理解,并帮助他人了解到底是什么,而不是重复下面?
抽象和封装是相辅相成的概念:抽象的重点在于一个对象的可观察的行为…封装着重于引起这种行为的实现…封装通常是通过信息隐藏实现的,这是隐藏所有对其本质特征没有贡献的对象的秘密。
抽象是一个过程,只显示“相关”数据,并“隐藏”来自用户的不必要的对象细节。 考虑一下你的手机,你只需要知道按下什么button来发送消息或拨打电话,当你按下button,发送消息的方式,你的呼叫如何连接,会发生什么?用户。
封装是将数据和function组合成一个称为类的单元的过程。 在封装中,数据不是直接访问; 它是通过课堂上存在的function来访问的。 用简单的话来说,类的属性保持私有,公共的getter和setter方法被提供来操纵这些属性。 因此,封装使得数据隐藏的概念成为可能。
抽象是隐藏信息或只提供必要的细节给客户。
例如汽车刹车 – 你只知道踩踏板会使汽车停下来,但你不需要知道它是如何工作的。
抽象的优点明天,如果制动器的实现从鼓式制动器变成了盘式制动器,作为客户端,你不需要改变(即你的代码不会改变)
封装将数据和行为绑定在一个单元中。 它也是一种限制访问某些组件的语言机制(这可以通过访问修饰符来实现,比如private,protected等)
例如, 类有属性(即数据)和行为(即对这些数据进行操作的方法)
抽象是概括的术语。 即封装是抽象的子集。
抽象是pipe理复杂系统的有效方法。 抽象是由定义良好的对象及其分层分类来pipe理的。
例如 ,汽车本身就是一个定义明确的物体,它由几个其他较小的物体组成,如齿轮系统,转向机构,发动机等,这些物体又有自己的子系统。 但对于人类来说,汽车是一个单一的对象,即使其内部细节未知,也可以通过其子系统的帮助进行pipe理。 礼貌
封装:将数据成员和方法合并成一个单元(即类)称为封装。
封装就像封装在胶囊中一样。 那就是将与一个对象有关的相关操作和数据包含在那个对象中。
封装就像你的包,你可以保留你的笔,书籍等。这意味着这是封装成员和function的属性。
class Bag{ book; pen; ReadBook(); }
封装意味着隐藏对象的内部细节,即对象如何做某事。
封装可以防止客户端看到抽象的行为被实现的内部视图。
封装是一种用于保护对象中的信息与其他对象的技术。
隐藏数据以实现安全性,例如将variables设置为私有数据,并将该数据公开以访问私有数据。
所以,当你访问属性时,你可以validation数据并设置它。 礼貌
一个使用C#的例子
//abstraction - exposing only the relevant behavior public interface IMakeFire { void LightFire(); } //encapsulation - hiding things that the rest of the world doesn't need to see public class Caveman: IMakeFire { //exposed information public string Name {get;set;} // exposed but unchangeable information public byte Age {get; private set;} //internal ie hidden object detail. This can be changed freely, the outside world // doesn't know about it private bool CanMakeFire() { return Age >7; } //implementation of a relevant feature public void LightFire() { if (!CanMakeFire()) { throw new UnableToLightFireException("Too young"); } GatherWood(); GetFireStone(); //light the fire } private GatherWood() {}; private GetFireStone(); } public class PersonWithMatch:IMakeFire { //implementation }
任何穴居人都可以发火,因为它实现了IMakeFire的 “function”。 有一组消防队员(名单)这意味着穴居人和PersonWithMatch都是有效的select。
这意味着
//this method (and class) isn't coupled to a Caveman or a PersonWithMatch // it can work with ANY object implementing IMakeFire public void FireStarter(IMakeFire starter) { starter.LightFire(); }
所以你可以有很多具有大量细节(属性)和行为(方法)的实现者,但是在这种情况下重要的是他们能够发挥作用。 这是抽象的。
由于制造火灾需要一些步骤(GetWood等),这些都是隐藏的,因为它们是class级的内部关注点。 穴居人有许多其他公共行为可以被外界调用。 但有些细节总是隐藏起来,因为与内部工作有关。 他们是私人的,只存在于对象中,他们从不暴露。 这是封装
抽象是从计划在devise中捕获/表示的实体中“抛弃”不必要的细节,并只保留与您的域相关的实体的属性的过程。
例如:代表汽车,例如型号和价格,当前位置和当前速度,忽略座位的颜色和数量等。
封装是属性的“绑定”和在一个抽象单位(即一个类)中操作它们的操作。
所以车子会有accelarate
位置和当前速度的accelarate
stop
。
数据抽象:访问任何类的数据成员和成员函数简称为数据抽象…..
封装:绑定variables和函数或1可以说数据成员或成员函数在一个单一的单元被称为数据封装….
封装可以被认为是用来将数据和function绑定在一起的包装纸,作为一个单一的单元,保护它免受各种外部污染(我的意思是外部function)。
抽象涉及没有细节和使用一个简单的界面来控制一个复杂的系统。
例如,我们可以通过按下button来点亮灯泡,而不用担心底层的电气工程(抽象)。
但是你不能以任何其他方式点亮灯泡。 (封装)
public abstract class Draw { public abstract void drawShape(); // this is abstraction. Implementation detail need not to be known. // so we are providing only necessary detail by giving drawShape(); No implementation. Subclass will give detail. private int type; // this variable cannot be set outside of the class. Because it is private. // Binding private instance variable with public setter/getter method is encapsulation public int getType() { return type; } public void setType(int type) { // this is encapsulation. Protecting any value to be set. if (type >= 0 && type <= 3) { this.type = type; } else { System.out.println("We have four types only. Enter value between 0 to 4"); try { throw new MyInvalidValueSetException(); } catch (MyInvalidValueSetException e) { e.printStackTrace(); } } } }
Abstraction
与实现细节未知的方法有关,这是一种实现隐藏。
Encapsulation
与实例variables绑定方法有关,是一种数据隐藏。
数据抽象 :DA只是过滤具体项目。 通过课堂我们可以实现纯粹的抽象,因为在创build课程之前,我们只能考虑有关课程的有关信息。
封装 :这是一种机制,我们通过这种机制保护我们的数据免受外部的影响。
那么我将用一个真实世界的例子来解释抽象。 在你家里说,你有一个电插头,许多设备可以连接到同一个插头,但插头永远不知道它连接到哪个设备,换句话说,设备的细节被抽象(隐藏)到插头。
想想如果我们直接将设备连接到没有插头的电线? 说直接连接一个灯泡到电线,然后电线知道它连接到哪个设备,当我们需要更换灯泡,那么我们必须从灯泡,这意味着灯泡与电线紧密耦合的电线连接删除。 换句话说,灯泡和电线知道它连接到的细节,意味着不是抽象的。
在面向对象的世界抽象工作完全一样。 使用其他类的函数/属性的类不需要知道它正在消耗哪些类的函数/属性,所有的东西都应该用接口/抽象类抽象出来。
让我编码相同的例子。 在这里我有一个类“ElectricPlug”,它正在运行一个设备。 但是“ElectricPlug”类没有任何想法正在运行的设备。 它可以是实现接口“IDevice”的任何类,这意味着从“ElectricPlug”抽象出“RunDevice”的实现。 这里是完整的示例代码,
class Program { static void Main(string[] args) { ElectricPlug electricPlug = new ElectricPlug(new Bulb()); } } public class ElectricPlug { private readonly IDevice _device; public ElectricPlug(IDevice device) { _device = device; } public void Run() { _device.Rundevice(); } } public interface IDevice { void Rundevice(); } public class Bulb : IDevice { public void Rundevice() { Console.WriteLine("Switched on bulb"); } }
封装是它听起来像是一种围绕某物保护其内容的方式。 抽象是提取某些东西的function属性,这样你就可以只使用你已经提取的内容而不知道内部运作情况来执行操作。
当我们说两种物质是液体时,我们使用“液体”作为对这些物质性质的抽象,我们正在讨论这些物质的性质。 这种抽象告诉我们,我们可以做的事情与我们以前的液体经验的物质。
抽象也跟真诚无关。 你可以有另一种抽象,如“金属”,以不同的方式提取物质的属性。
抽象概念忘记了细节,所以如果你正在使用一个特定的抽象概念,你不应该询问那些抽象概念所没有给出的基础实体的属性。 就好比如果你把牛奶和水混合在一起,你就很难问你有多less牛奶。
Functor是一个抽象的东西,它有一些map的概念,也就是说,你可以在内部的内容上运行一个函数,把内部的位转换成其他的东西。 外面的东西保持着同样的东西。
在这里得到有用的是,如果你有一个函数在列表上工作,你意识到你只依赖于地图界面,你可以依靠函数,然后你的函数可以使用stream,承诺,maybes,元组和分享抽象的其他任何东西。
像Haskell这样的函数式语言具有一些非常强大的抽象能力,使得极端的代码重用成为现实。