奥马尔孤独

面向对象的编程(OOP)是一个编程范例,专注于使用对象作为软件构建块。这种范式非常类似于人类如何在现实生活中感知物体,从而降低与软件开发相关的复杂性。必威真人投注

为什么面向对象编程是有价值的

计算机程序可以用各种编程语言编写。这些语言使用不同的概念和范例来构造程序中的代码。在现代软件开发中,面向对象编程语言通常必威真人投注用于编写大型和复杂的软件。面向对象编程的发展是为了降低软件开发的复杂性,使构建和扩展大型软件程序变得更容易必威真人投注

用UML进行面向对象分析、设计和编程

2020年11月

畅销书
  • 126次讲座
  • 所有级别
4.5 (452)

学习在c++, Java和c#中使用UML进行OO分析,设计和编程由Umar孤独的

探索课程

软件开发本质上是复必威真人投注杂的。导致复杂性的一些因素包括:

完全解决与软件开发相关的复杂性几乎是不可能的,但它可以在很大程度上降低。必威真人投注

解决复杂性:算法分解与面向对象分解

人类以不同的方式解决复杂性。面对问题时,我们往往把它简化。其中一个简化过程叫做“分而治之”在拉丁语中,意思是“分而治之”。根据这一原则,问题被分解成更小的部分。对于每个部分,我们创建一个解决方案并将它们链接在一起。这与我们解决复杂算术问题的方式非常相似。

这是解决复杂性的常用方法。难怪早期的编程语言(如Cobol、Pascal和C)就是基于这个概念的。该解决方案被实现为一组算法,其中每个算法算法由函数或过程表示。这就是为什么这些语言被称为过程语言。这些语言使用函数作为程序的基本构件。这也被称为自顶向下设计

这些语言将问题分解为一组算法。这就是所谓的算法分解.过程性语言使用算法分解的过程来解决复杂性。

对于大规模的软件开发,算法分解不会很好地缩放。必威真人投注它无法管理发展大型应用程序的复杂性。该应用程序由一个在另一个之后调用的函数组成。这使得它们彼此紧密耦合并依赖,导致以下问题:

使用算法分解的软件可以用图表示为:

这通过算法分解增加了软件开发的复杂性。必威真人投注

然而,人类还有另一种处理复杂性的方法。当我们与事物交互时,我们倾向于认为它们是提供某些功能的对象。不仅如此,我们还创建了对象的简化视图,忽略了与我们无关的细节。这个过程叫做面向对象的分解因为系统被看作是一组协作对象,每个对象都有一个角色要扮演。这个也叫做a自下而上设计

由对象组成的系统可以由下图表示。

每个圆形块代表一个对象。这些线代表对象之间的交互。每个对象:

这表明对象通过消息(用线表示)彼此通信。这与我们在现实生活中如何感知和与其他物体互动密切相关。我们处理对象的行为而不考虑内部实现细节。例如,当我们开车时,我们不处理它的内部实现。相反,我们通过发送诸如转向、加速和制动等信息来驱动它。因此,整个驾驶过程变得简单。

同样,面向对象的分解简化了软件开发过程。必威真人投注它有助于管理大型软件项目的复杂性。

让我们比较一下算法分解和面向对象分解:

算法分解 面向对象的分解
系统分为作为函数/过程实现的算法 系统被闯入协作对象
基本构建块是一个函数 基本的构建块是一个对象
函数依赖的数据可能是全局的 对象有自己的数据
数据是全局的,因此任何人都可以修改数据 数据是对象的私有数据,只有该对象才能修改它
函数按顺序相互调用来进行通信 对象通过消息传递(方法调用)相互交互
函数之间是紧密耦合的 对象之间是松散耦合的
函数不容易重用 易于重用对象
添加新功能是困难的 可以通过新对象添加新要素
不能代表现实生活中的实体或模拟它们的交互 现实生活实体可以通过没有不必要的细节来表示的
使用自顶向下的设计 使用自底向上设计
对于大型软件来说不符合良好 适合大型软件

这个比较清楚地显示了为什么面向对象分解是解决软件复杂性的更好方法。面向对象分解的核心是一个对象。我们将在下一节对此进行深入讨论。

定义物件

对象是可识别的项目或实体,可以是真实的或抽象的,并在问题域中提供一些功能。

对象可能是存在于现实世界中的物理对象。现实世界中的物体有一棵树、汽车或房子。它也可能是一个没有物理形式的抽象物体。它可能不是有形的,但仍然存在,并代表着一些重要的东西。例如,银行帐户是一个抽象对象。它没有具体的形式,但代表了一个人的资金。在软件系统中,我们使用抽象对象来定义程序中的特定实体。

每个物体都有以下三个特点:

让我们使用扬声器系统的示例来理解这些特征。

状态

状态对象的属性可以是静态的,也可以是动态的。

扬声器系统的状态可能包括以下属性:

Volume是一个可以随时间变化的动态属性,而列出的其他属性是静态的,永远不会改变。

属性可能有以下值:

输出功率 100瓦
连接 蓝牙
制造商 罗技
序列号 ABCD1234
类型 5.1
体积 50%

属性值表示对象的状态——在本例中,上面的值表示特定扬声器系统的状态。

身份

对象的标识可以通过能够唯一标识该对象的属性来表示。在我们的扬声器系统示例中,通过序列号提供唯一标识。

行为

每个对象都将提供一些功能作为其职责的一部分,该功能由其行为.speaker系统将提供以下行为:

调用这些行为将导致扬声器系统以某种方式做出响应。注意,在调用行为时,我们不处理内部实现。

从a创建一个对象

在编程语言中,一个对象来自一个类。可以创建任意数量的类对象。类是一个模板或蓝图,列出其对象的属性和行为。类包含数据和函数。功能通过对象对数据进行操作。

对象是通过实例化类来创建的。这个过程用可以通过调用对象的行为来修改的值来初始化属性。属性中的值构成了对象的状态。每当一个类被实例化时,它就会创建一个带有新状态的新对象。

因此,对象是面向对象编程的基本构建块。

面向对象编程

OOP是一种使用类和对象作为其构建块的编程范例。它是基于一个叫做对象模型.该模型包含定义面向对象编程概念的四个主要元素:

实现对象模型元素的语言称为面向对象语言,如Java、c++、c#和Python。即使这些语言支持这些特性,如果不理解这个概念框架,在这些语言中编程仍然看起来像算法,而不是类和对象。如果这种情况发生在您的工作中,很可能是因为您没有正确理解问题或领域。您的设计仍然会有一种过程的感觉,并且包含一些函数/过程,这将使其难以扩展、重用和维护。

让我们理解对象模型的四个元素。

抽象

抽象是人类用来处理复杂性的基本方法之一。它让我们只关注相关的细节,而忽略或抑制不需要的细节。这让我们形成一个抽象这代表了对象的整个基本行为。

在对象模型中,抽象可以同时引用过程和一个实体.抽象作为一个过程处理提取一个项目的重要细节。抽象作为一个实体指抽象过程的结果。

执行抽象是面向对象编程的第一步。这使我们能够专注于重要的方面而忽略不重要的方面。在面向对象语言中,类将抽象表示为实体。类可以表示具有所需行为的真实对象。这些类是通过实体抽象创建的,因为它们直接表示存在于问题域词汇表中的对象,从而简化了我们对系统的理解。

以第一人称射击电脑游戏为例。玩家的目标是到达森林边缘,那里居住着怪物。玩家有一把枪用于防御和攻击怪物。如果我们执行面向对象的分解,我们会在游戏中发现以下主要对象:

下一步是用面向对象编程语言表示这些对象。但是,我们必须确定在这些对象中我们想要的细节级别。为了简单起见,让我们只关注玩家。玩家是控制游戏的人。一个人有一长串属性,例如:

游戏中的大部分都不是必需的,并且在该领域不相关。控制玩家的人的相关细节是:

可能更多地取决于游戏的类型,但对于这个例子,这些是我们游戏中最重要的。

这是抽象的结果。我们创建了一个包含相关细节的实体,并忽略了其他部分,因为它们不是必需的。这降低了与对象相关的复杂性。

让我们在Java程序中实现这个抽象。英语是一种很流行的语言,很容易学。有无数的Java教程和数以千计的书籍可以帮助你学习和编写程序。

现在,我们可以通过班级代表玩家..

class Player {public int health=100;public String name;};

您可以指定与您的抽象相关的任何数据类型。在这个抽象中,int和String类型与我们想要捕获的信息相关,并表示数据的概念球员.这两个数据类型成为类的成员,并且称为字段或数据成员。

的实例创建后球员,我们可以为此特定播放器分配名称和健康。但是这个课程有一些问题:

抽象本身并不是很有用,因为客户可以看到内部。因此,我们将通过隐藏其内部细节封装

封装

封装是抽象后的逻辑步骤。它隐藏了抽象的实现细节。它也被称为信息隐藏,作为关于如何实施类的信息是隐藏的来自外部世界。反过来,抽象负责向客户机提供其功能。

因此,我们示例中的下一步是添加实现球员类,但不暴露细节。让我们修改Player类并封装它。

班级球员{私有INT health = 100;private String名称;公共空白攻击(敌人){//实施}公共空缺武田(int损坏){health  -  =伤害;If(健康< 0)健康= 0;Public Int Gethealth(){返回健康;}公共布尔alive(){返回健康!= 0;}}

抽象现在通过添加方法(类内部函数)封装。由于这些方法是类的一部分,因此他们可以访问类的私有成员,包括类的字段。

这样,我们就创建了字段和方法的绑定。这些将共同提供类的功能。

类的内部细节现在通过封装隐藏起来了。所有数据成员(字段)都是私有的,因此在类之外无法访问它们。

封装其实现的类有以下几个优点:

假设我们决定在之后的游戏设计中添加对盔甲的支持。的实现可以修改takeDamage ()解释对损害较少的方法球员当它有盔甲的时候。客户端不必在实现中看到这种变化takeDamage ()方法。

我们也可以实现敌人类如下:

类敌人{int生命值= 100;int力量;public void takedage (int damage) {health -= damage;If(健康< 0)健康= 0;} public void attackPlayer(Player Player){//实现}}

游戏的碰撞系统将调用适当的行为球员敌人对象取决于游戏玩法。

最后,记住抽象和封装是密切相关的。抽象提供了实现,而封装隐藏了它的实现细节。

层次结构

这指的是类和/或对象之间的关系。软件中的对象,就像现实生活中的对象一样,不是孤立存在的。它们与其他物体相互作用,并可能表现出某种关系。为对象分配层次结构简化了我们对对象如何相互协作的理解。有两种方法可以定义关系——对象组合和类继承。

如果一个对象具有另一个对象所需的功能,我们可以使用作文的关系。在组合中,一个对象将在另一个对象中组合。这也被称为局部的关系。这种关系表现在物体上。

在我们的例子中球员职业可以用枪攻击怪物。射击行为可以由调用的另一个类提供.而不是重新实现这个功能球员班级将简单地重用它.因此,球员类将组成实例。

class Gun{int bulletDamage = 10;int bulletCount = 50;public int shoot(){//减少子弹数量返回bulletDamage;} //其他方法,如reload, pickammo等}class Player{private Gun Gun = new Gun();Private int health = 100;private String名称;public void attack(Monster Monster) {int damage = gun.shoot();monster.takeDamage(伤害);} //实现的其余部分

这种方式,球员类不需要重新实现枪的功能。它可以通过简单的组合来重用该功能实例。

通过泛化创建其他关系。概括代表不同单独对象的共同特征。例如,汽车是不同类型的汽车的概括 - 它代表了汽车的所有共同属性和行为。所以,我们可以说BMW或Tesla是一种汽车。两者都提供了汽车的行为,但以不同的方式提供。这被称为“类型”或“是”的关系。在面向对象的编程中,我们将其称为继承. 这种关系适用于类。

继承允许我们将不同类的共同特征放入一个广义类中。广义类称为超类或基类。其他类将继承这个类的特性,称为子类或子类。基类表示它的子类可能提供的所有特性,尽管是以不同的方式。这种类的排序被调用类层次结构

这种方法的优点是:

在我们的电脑游戏例子中,我们想要添加不同类型的敌人以保持游戏玩法的趣味性。每个敌人都有自己的属性和攻击玩家的不同方式。一些敌人是:

敌人 的攻击方式
狼人 爪子

为了攻击这些敌人球员班级必须了解他们的相应课程。这需要修改球员和课程之间的紧密耦合。如果我们将来添加更多课程,我们必须重复修改球员班每次修改都可能引入bug,并以意外的方式破坏代码。bug可能累积到软件最终失败的程度。

这种依赖关系可以用图形表示:

我们应该尽量减少类之间的依赖关系。的依赖关系球员课上狼人类。

狼人分享一些属性和行为。例如,两者都会有健康和力量。两者都会以自己的方式攻击玩家。因此,我们应该能够通过创建包含所有敌方类的共同功能的类来概括它们。我们打电话给这个课怪物

类怪物{private int health=100;private int strength;public Monster(int strength){this.strength=strength;}public void takeDamage(int damage){health-=damage;if(health<0)health=0;}public void attackPlayer(){//Implementation}

在Java中,我们使用关键字延伸表示继承关系。下面是实现狼人类:

class狼人扩展怪物{公共狼人(int strength) {super(strength);} public void attackPlayer(){//用爪子攻击}}class Dragon extends Monster{int fireDamage;public Dragon(int strength,int fireDamage) {super(strength);这一点。火Damage = fireDamage ; } public void attackPlayer() { //Implementation } }

类的子类继承怪物而是提供自己的实现攻击玩家()方法。这是必要的,因为它们会以不同的方式攻击玩家。因此,他们可能会添加自己的实现,除了他们从Monster继承的。你们可能注意到了类具有支持其攻击模式的属性。然而takeDamage ()方法实现对所有类都是通用的,不需要在子类中重新实现。

现在,唯一的问题是玩家课程如何与这些类交互?答案是通过基类怪物.记住,怪物表示所有子类的泛化。它的对象可以保存对子类对象的引用。

怪物怪物=新的狼人(20);monster.attackPlayer ();

在这种情况下怪物对象保存对的引用狼人.子类型,狼人,转换为怪物通过一个称为类型转换的过程。这仅仅意味着将一种类型转换为另一种类型。在这种特殊情况下,转换的类型称为上行转换,因为转换是从子代到父代。当将子实例赋值给基类引用时,将自动应用此强制转换。这允许我们使用狼人对象通过怪物参考。

现在球员只需要与之互动怪物类,而不必处理它的子类。

这可以如下图所示:

请注意,依赖关系是如何减少到只有一个连接球员怪物基类。现在我们可以添加更多的怪物到游戏中而不需要修改球员班级。

球员类应该能够在不知道是谁的情况下向不同类型的怪物发送消息(调用方法)。我们会更新攻击()中的方法球员如下:

public void attack(Monster Monster) {Monster .take damage (20);}

你可能想知道当takeDamage ()方法在monster引用上调用。它应该调用正确对象的方法,而不是怪物班级。这可以通过多态性来实现。

多态性

多态意味着“多种形式”。这与对象之间传递的消息有关。当一个对象向另一个对象发送消息时,目标对象应该正确响应。如果目标对象是内部引用子对象的基类对象,则消息将自动转到子对象。

在我们的例子中,消息是方法调用:takeDamage ().的狼人课程已重新实施takeDamage ()方法并提供了自己的实现。这叫做方法重写,不要将其与方法重载混淆。被覆盖的方法被称为多态的

当调用此重写方法时怪物的方法,则调用潜在的对象,而不是怪物参考。在编译时还不知道将调用哪个对象的方法。此解析将在运行时进行。这也被称为动态多态性

在Java中,默认情况下,所有方法都是多态的,可以被覆盖。在其他语言中,您可能必须使用关键字来指示重写行为。例如,c#和c++使用虚拟关键字。注意,只有多态方法可以被覆盖。

然而,在Java中,我们使用@Override注释,以指示要重写的意图。注意,它的用法是可选的。

class狼人扩展怪物{公共狼人(int strength) {super(strength);} @Override public void attackPlayer(){//使用爪子攻击}}

在其他情况下,还可以实现编译时多态性。要调用的方法是在编译时决定的,通常是通过方法的参数。在面向对象语言中,这是通过函数重载实现的。

多态有几个优点:

结论

现代软件开发中使用的大多数语言都实现了对象模型的概念框架。必威真人投注这样的语言使我们能够创建大规模的软件。它们通过抽象、层次结构和其他元素帮助降低复杂性。

这些是人类处理复杂性的自然方式。将已知元素集成到语言中可以降低与软件开发相关的总体复杂性。必威真人投注

应用程序必威真人投注的开发不会在产品发货后结束。软件只是进入了一个不同的维护阶段——这种维护仅仅意味着对现有软件的更改。它包括错误修复、添加新组件、弃用旧的或不需要的功能,等等。在已经部署的软件中进行这些更改是困难的。这些变化可能也必须在开发阶段进行整合,这也带来了自身的一系列挑战。

如果软件是用对象模型的概念框架编写的,那么软件组件将是松散耦合的。这简化了对现有软件的修改,因为更改将本地化到特定的组件。它的修改不会影响软件的其他部分。同样,我们也可以通过简单地添加新类来添加新特性。

因此,我们已经看到了面向对象编程如何简化了软件开发的整个过程。必威真人投注这就是为什么这是现代软件开发中最常用的编程范例。必威真人投注

然而,存在面向对象的编程的替代方法,例如功能编程,通用编程和程序编程。大多数现代语言都支持多个范式,程序员利用编写更复杂的程序。

页面上次更新:2020年10月

面向对象编程的顶级课程

c#中级:类、接口和OOP
狂舞Hamedani
4.6 (25500)
畅销书
用UML进行面向对象分析、设计和编程
奥马尔孤独
4.5 (452)
畅销书
Java适用于所有人——从零到英雄
的孩子叫库马尔
4.3 (1,040)
掌握使用Python的4项关键技能
穆斯塔法·萨阿德·易卜拉欣博士
4.7 (557)
评价最高
PHP OOP:面向对象编程初学者+项目
埃德温·迪亚兹,编码学院解决方案
4.4 (3,383)
超越基础的Python -面向对象编程
无限的技能
4.5 (2812)
Java中面向对象编程的绝对介绍
Imtiaz Ahmad.
4.4 (4,816)

更多面向对象的编程课程

面向对象编程的学生也会学习

授权你的团队。引领行业。

通过Udemy for Business订阅您组织的在线课程和数字学习工具图书馆。

请求一个演示

Umar Lone的课程

完全现代C++(C++ 11/14/17)
奥马尔孤独
4.5 (3,518)
用UML进行面向对象分析、设计和编程
奥马尔孤独
4.5 (452)
畅销书
C/ c++指针和应用程序
奥马尔孤独
3.9 (115)
在C/ c++应用程序中检测内存泄漏
奥马尔孤独
4.1 (72)
现代c++中的创造性设计模式
奥马尔孤独
4.7 (77)
现代C ++中的结构设计模式
奥马尔孤独
4.7 (26)
开始C ++模板
奥马尔孤独
4.5 (1028)

Umar Lone的课程