面向对象与算法之间的关系


9

当我阅读一些算法教科书时,它们充满了解决某些问题(排序,最短路径)或某些常规方法(递归算法,除以征服,动态编程等)的巧妙程序。我在那里发现了很少的面向对象编程的痕迹。(为什么它们更面向过程?)。

然后我在想:

  • 算法和OOP之间有什么关系?他们是两个独立的主题吗?
  • 是否存在一些只能由OOP提出和解决的问题?
  • OOP如何帮助算法?或会在哪个方向影响它?


@DocBrown谢谢,这非常有帮助,但是在这里我们可以考虑围绕OO的一些概念,例如继承,多态……
Ahmad

1
“为什么算法教科书更注重过程?” Java也是面向过程的。Java是一种面向对象的过程语言。
Pieter B'2


1
@gnat我修改了我的问题,不知道这些解释是必要的还是不好的。但是,我承认布朗博士解决的问题有更多与我的担忧有关的答案。
艾哈迈德(Ahmad)2015年

Answers:


10

首先,让我们定义OOP的含义。OOP我主要是指:

  • 封装和隐藏类中的细节。
  • 通过继承和虚拟方法实现行为多态。

现在,回答您的问题:

算法和OOP之间有什么关系?他们是两个独立的主题吗?

是。

是否存在一些只能由OOP提出和解决的问题?

不。OOP主程序为程序员提供了方便和推理代码的能力。它不会增加您的表达能力。

OOP如何帮助算法?或会在哪个方向影响它?

就像我上面说的。我描述OOP的两点都适用于此。能够隐藏算法及其数据结构的细节可以帮助推理整个过程。许多算法包含您不希望该算法的用户弄乱的细节。隐藏这些细节很有帮助。

具有多态行为的能力也很好。List被定义为能够在集合中的任何位置添加/删除/清除项目。但是,它可以实现为可调整大小的数组,双向链接或单链接等等。将单个API用于多个实现可以帮助重用。

为什么算法教科书更注重过程?

就像我说的那样,OOP并不是实现算法所必需的。同样,当OOP尚未普及时,许多算法已经过时并且创建了。因此这也可能是历史性的事情。


1
尽管有很多文章,您可能不希望仅仅因为它是现代的而混淆使用OOP的算法。
Gusdor

15

算法OOP是两个完全不同的术语,它们的共同点是CS术语。简单-算法就像烹饪食谱:要做x,您需要以下成分并执行步骤1,2,3,4,5,6 ...,然后准备好饭菜。

就是说,以程序的方式描述算法似乎是很自然的选择。程序意味着:首先执行x,然后执行y

一个常见的问题是:»如何对一组x?« 进行排序。一个易于理解的解决方案是bubble-sort

  1. 只要您还没有到达第一个元素,就在最后一个元素上迭代集合
  2. 从第一次迭代的开始到当前元素开始第二次迭代,然后
  3. 比较(2)的当前元素及其后续元素
  4. 如果更大,则调换头寸

这是-算法的算法/语言描述bubblesort

这是程序/伪代码的实现

bubbleSort(Array A)
  for (n=A.size; n>1; n=n-1){
    for (i=0; i<n-1; i=i+1){
      if (A[i] > A[i+1]){
        A.swap(i, i+1)
    } 
  } 
}

那很简单。

那如何与OOP相关?您可以使用此算法来治疗收集的(对象本身)的对象

用Javascript编写示例(尽管没有干净的OO-Lingo,但几乎没有样板,而且易于理解)

objects =[{"name":"Peter"}, {"name":"Paul"}, {"name":"Mary"}]

compareObjects=function(x,y){ return x.name>y.name };

sorted = objects.sort(compareObjects)

console.log(sorted)

我们有一个)集合objectsb)该集合通用的方法,sort其中包含/抽象了排序算法,以及c)我们的对象PeterPaulMary。可以在此处找到排序规范。

算法和OOP之间有什么关系?他们是两个独立的主题吗?

从所说的来看,应该明确的是,答案应该是:是的,它们是独立的。

OOP如何帮助算法?或会在哪个方向影响它?

OOP只是一种编程风格。它无济于事。否则,可以用OO语言实现一种算法来对对象做一些事情(如图所示)

是否存在一些只能由OOP提出和解决的问题?

我想不出一个(但这并不意味着那是不可能的)。但是,如果从另一个角度来看:如果要对一些问题建模并使用适当的算法来解决,则OOP非常有用。假设您有记录,friends可以像objects对它们那样进行建模,properties并且如果您希望以任何方式list对它们friends 进行排序,则可以使用上面给出的示例代码来做到这一点。

为什么算法教科书更注重过程?

如前所述:这是更自然的,因为过程是算法的特征


7
该答案以算法自然是程序为前提。当然有一些,但是有功能算法之类的东西。算法书籍之所以具有程序性,可能与它们专注于性能这一事实有关,因此,由读者来担心强制执行抽象,因为命令式语言比功能性语言更受欢迎。
2015年

我认为那是不对的。在谈到函数式编程语言时,您是在谈论实现,而不是算法本身。举个例子Haskell的快速排序 wiki.haskell.org/Introduction#Quicksort_in_Haskell我们都同意,这是一个功能实现的快速排序,algortihm。但是,如果您描述,该怎么做,您就必须以描述性的描述方式回退。从此描述中,您可以实现程序实现。
Thomas Junk

1
@ThomasJunk你不要有回落到描述的程序模式,因为功能实现说有什么事情,不连续的步骤。您将如何为纯延迟计算给出顺序描述?您不会预先知道将对多少个表达式求值,也不知道将按什么顺序计算它的子表达式。
2015年

2
不幸的是我没有CS学位,所以我缺乏广泛的技能来证明以下内容:但是我认为每种算法都可以用一种或另一种方式描述,因此没有真正的纯功能算法。是不是,旅行的完整性意味着什么?
Thomas Junk

2
@Doval很好,因为Turing自己证明了lambda演算和Turing机器是等效的,那么很明显,您可以以功能性方式陈述的一切,都必须执行。将懒惰的计算转换成命令式的命令也是微不足道的-Haskell的编译器一直都在执行它……最后,这只是一个偏好问题。有时功能更合适,有时势在必行,而有时逻辑则是最好的……
AK_15年

5

你有问题。

业务域模型描述了您的问题,并且您正在处理的问题域中的概念也正在处理。

算法从概念上描述了解决问题的方式。您的实现会是什么样子?以及将问题翻译成“计算机科学”术语后如何处理。

OOP,功能,逻辑,过程乃至非结构化的编程范例描述了如何构造解决方案,采用哪种形式,采用哪种“软件工程”概念以及采用哪种“编程语言理论”的概念。

简而言之,算法通常描述了您对问题的解决方案(“这就是我要做的事情”)。当编程范例处理您的实际实现时(“这就是我要做的事情”)。


请注意,声明性语言可能以不完美的方式来减少或消除“操作”步骤。他们的目标是让您简单地说“这就是我想要的”(例如,通过编写高级方程式)。考虑一个典型的SQL查询:很少有“算法”查询;您只需告诉数据库您想要什么,就取决于它如何处理您的请求(当然,在某些限制下)。
安德烈斯·F

4

算法 =讲述“ 如何做 ”的故事(即,如何及时使用数据结构操纵输入数据以产生期望的结果)

OOP = OO语言促进的“ 方法论 ”来编写程序(=算法+数据结构),从而为您提供内存安全性和抽象性

OOP只是实现算法的范例。

打个比方:电影

您可以通过雇用或不雇用特技演员来记录场景。剧本(算法)不变。人们不应该看到最终结果的任何差异。

编辑:您可以尝试高质量的MOOC:https//www.coursera.org/course/algs4partI,它交错讨论的主题(尤其是OOP方法),并提供了您在此处提出的要点。


我真的很喜欢你的电影比喻。我将来会借用那个。
马克·拉弗勒

2

Alexander Stepanov是C ++标准模板库(STL)的原始创建者,该库是C ++的基础算法库。C ++是一种多范式语言,其中包含“面向对象”功能,但是Alexander Stepanov谈到了面向对象:

http://www.stlport.org/resources/StepanovUSA.html

STL不是面向对象的。我认为面向对象几乎和人工智能一样是个骗局。我还没有看到来自这些面向对象的人的有趣代码。

我发现OOP在技术上是不完善的。它尝试根据一种类型上不同的接口来分解世界。要解决实际问题,您需要使用多种代数-跨多种类型的接口族。我发现OOP在哲学上是不完善的。它声称一切都是对象。即使这是真的,也不是一件很有趣的事情-说一切都是一个物体,根本什么也没说。我发现OOP在方法上是错误的。它从类开始。好像数学家会从公理开始。您不是从公理开始的,而是从证明开始的。只有找到了一系列相关的证明,才能提出公理。您以公理结尾。编程中也是如此:必须从有趣的算法开始。只有了解得好,

在理解为什么这种机制从根本上存在缺陷并且不应该使用该机制之前,我花了多年的时间尝试为继承和虚拟化找到某种用途。

Stepanov并非使用Objects而是使用Generic Iterators来表达他的算法库。


好吧,他错了……主要是因为STL很大程度上是面向对象的……自术语以来,面向对象的东西就更现代了……
AK_

1
@AK_-我认为他根本没有错。从任何意义上讲,STL甚至都不是OO。您可以将STL直接转换为具有参数多态性的非OO语言(例如,Haskell或SML),而无需进行任何实质性更改。
2013年

2

算法描述了计算机应该做什么。结构描述了算法的布局[源代码]。OOP是一种利用某些“面向对象”结构的编程风格。

算法书籍通常避开OOP,因为它们专注于算法而不是结构。严重依赖于结构的代码片段在编写算法书时往往是不好的例子。同样,OOP书籍通常避开算法,因为它们使故事变得混乱。OOP的卖点是它的流动性,将其与算法挂钩会使它显得更加僵化。 最重要的是书的重点。

在现实生活的代码中,您将同时使用两者。 根据定义,没有算法就无法解决计算机问题,而且如果没有结构(OOP或其他方式),您将很难编写好的算法。

作为动态模糊的示例,请使用动态编程。在算法书中,您将描述如何在数组中获取同质数据集并使用动态编程来得出解决方案。在OOP书中,您可能会遇到“访客”之类的结构,这是一种对一组异构对象执行任意算法的方法。DP书籍示例可以被认为是一个非常简单的访客,通常以自下而上的顺序操作对象。可以将“访客”模式视为DP问题的框架,但缺少肉和土豆。实际上,您会发现两者经常同时需要:使用Visitor模式处理数据集中的异构性(DP不利于此),并且在Visitor结构中使用DP组织算法以最小化运行时间(Visitor没有

我们还看到算法在设计模式之上运行。在狭小的空间中很难用语言表达示例,但是一旦有了结构,就开始想要操纵该结构,并使用算法来做到这一点。

是否存在一些只能由OOP提出和解决的问题?

这是一个比您想象的要难回答的问题。首先,没有计算上的理由需要OOP解决任何问题。 简单的证明是,每个OOP程序都被编译成汇编语言,这绝对是非OOP语言。

但是,在更大的方案中,答案开始趋于肯定。 您很少仅受计算方法的限制。大多数情况下,诸如业务需求和开发人员技能之类的因素才是因素。如今,没有OOP不能编写许多应用程序,这不是因为OOP在某种程度上是该任务的基础,而是因为OOP提供的结构对于保持项目的正常进行和预算是必不可少的。

这并不是说将来我们永远不会因为一些有趣的新结构而放弃OOP。它只是说它是我们工具箱中最有效的工具之一,可以解决当今非常庞大的编程任务。未来的问题可能会导致我们使用不同的结构来进行开发。 首先,我希望神经网络需要一种非常不同的开发方法,这种方法可能会也可能不会是“面向对象的”。

由于算法设计师的想法,我认为OOP在不久的将来不会消失。迄今为止,通常的模式是有人设计了不利用OOP的算法。OOP社区意识到该算法并不真正适合OOP结构,并且实际上并不需要,因此他们将整个算法包装在OOP结构中并开始使用它。考虑一下boost::shared_ptr。内置的引用计数算法shared_ptr不是非常友好的OOP。但是,该模式直到shared_ptr在其周围创建一个OOP包装器(以OOP结构化格式公开算法的功能)后才流行起来。现在,它是如此流行,以致使其成为C ++的最新规范C ++ 11。

为什么如此成功?算法擅长解决问题,但是它们通常需要大量的初期研究投资才能了解如何使用它们。面向对象的开发非常有效地包装了这些算法,并提供了一个界面,该界面需要较少的初始投资来学习。


1

除了很好的答案,我还将提到OOP和算法之间的其他概念上的共性

OOP和算法都强烈强调使用前置条件和后置条件以确保代码的正确性。

总的来说,这是计算机科学所有领域的标准实践。但是,这种指导原则导致了OOP的发展之路,这使得在OOP环境中实现算法互惠互利。

在OOP中,可以使一组可以满足相同协定(前提条件和后置条件)的对象实现一个接口。除非在少数情况下(发生泄漏抽象的情况下),否则该接口的用户将不需要知道在底层对象中使用了哪种实现。

一种算法是用于执行计算的步骤的一种实现,它将采取前置条件并产生后置条件。

因此,人们可以以前置条件和后置条件的方式借用抽象概念,并将其应用于算法。您会发现有时复杂的算法可以分解为较小的步骤,只要满足相同的前提条件和后置条件,这些较小的步骤就可以允许使用不同的实现策略。

通过在OOP中实现算法,可以使这些较小的步骤互换。

最后,请记住FP和OOP并不互斥。上述任何内容同样可以同样适用于FP。


谢谢你的意思!如您所说,如果算法只是一些步骤,那么OOP可以帮助我们提供更多抽象的步骤。您指出“在OOP中实现算法”,我修改了问题以询问是否总是有益的?
艾哈迈德(Ahmad)2015年

1
您将OOP与“按合同设计”混淆了。如果没有OOP,它非常有用,而且大多数OOP语言(C#,Java)都不为其提供真正的支持(它们支持简单的接口,不支持前后条件)
AK_15年

1
@AK_我同意按合同设计是我答案中描述的通用性的正确名称。我所声称的是,OOP作为设计范式强烈接受“按合同设计”-只需阅读任何OOP教科书即可。我最初的回答还提到,这种共性不是OOP独有的。
rwong 2015年

-1
What is the relation between algorithms and OOP? Are they two independent topics?

算法是关于如何解决问题的(如何从给定的输入生成输出),OOP是关于如何制定或表达我们的解决方案(算法的步骤)。

可以用自然语言或汇编语言来描述算法,但是自然语言中的概念有助于我们更好地编写和理解它。例如,冒泡排序的算法可以是:

bubbleSort(Array A)
  for (n=A.size; n>1; n=n-1){
    for (i=0; i<n-1; i=i+1){
      if (A[i] > A[i+1]){
        A.swap(i, i+1)
    } 
  } 
}

为了隐藏细节swap并将其与A我们联系起来,我们使用了OOP语法和功能,然后OO使算法更接近我们的自然语言和理解。

Are there some problems which can only be presented and solved by OOP?

不,如果您认为计算机上的任何程序(或算法)都将转换为在CPU(图灵机)上执行的一组指令,并且如果我们将这些指令视为解决计算机上问题的最终算法,则OOP无法做进一步的事情。它只是使其更接近人类的理解和推理。这是打包我们的过程和数据结构的一种方式。

How OOP can help algorithms? Or in which direction it can affect it?

陈述或制定算法更容易或更容易理解可能会有所帮助。它可以隐藏细节并提供解决方案的概况。

从理论上讲,该算法是第一位的其次是实现。但实际上,在跟踪或生成预期输出之前,我们无法确定算法是否按预期工作。计算机可以帮助我们做到这一点,但是您不希望用机器语言(汇编语言)来编写它。

在这方面,OOP有助于在计算机上实现,测试和完善我们的算法,并以接近自然语言的语言为计算机编写算法。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.