【问题标题】:Erlang (Functional Programming) vs Object Oriented Programming in terms of thinkingErlang(函数式编程)与面向对象编程的思维方式
【发布时间】:2010-12-21 12:48:38
【问题描述】:

我正在学习 Erlang,我正在尝试创建一个非常示例的博客程序。然而,我的思想目前被困在 OO 世界中var p = new Post(); p.Title = ""; p.Save();)。我想了解一些 Erlang 的基本思想。我应该在数据结构(p.Title、p.DateCreated、p.Body)方面做什么,而不是创建 Post 对象?我应该使用元组吗?我想了解做这些事情的推荐方式(在 Erlang 特定和/或函数式编程特定)。还是我在 Erlang 或 FP 中做的根本错误?

需求(OO术语,不知道如何用FP术语解释^_^):

  1. 创建 Post 对象(id、title、date_created、body、IList)
  2. 创建评论对象(id、post_id、created_by(名称为字符串)、date_created)
  3. 一个帖子可以有多个 cmets
  4. post.AddComment(Comment)

谢谢。

更新: 我不是在寻找在 Erlang 中进行 OOP 的特定方法,除非它是推荐的方法。我正在寻找标准/推荐的方式来做问题中描述的事情,但是我不想在 Erlang 中复制 OOP。

【问题讨论】:

  • 您可以使用元组代替对象,但使用记录可能更清晰。 (无论如何,记录在 Erlang 中都会转换为元组。)
  • @Nate 谢谢你,因为我以前不知道这个关键字。这是一个顶级的谷歌搜索结果,仅供参考。 20bits.com/articles/erlang-an-introduction-to-records
  • @Nate 如何使用记录表示私有状态和方法?您能否解释一下如何有效地使用记录来替代类、接口等?
  • @Jeffrey:在 OO 术语中,您是否希望将所有对象都放在内存中,用指针引用,还是考虑将它们存储在某种 DB 中(可能使用 ORM)?跨度>
  • @Zed,目前,出于学习目的,我不会接触数据库(例如 Mnesia)。

标签: functional-programming erlang oop


【解决方案1】:

Erlang 一种面向对象的语言。如果您按照 Alan Kay 所描述的方式看待 OOP,则此声明更有说服力:

对我来说,OOP 仅意味着消息传递,本地 保留和保护和隐藏 状态过程和极端 所有事物的后期绑定。

您必须知道,Erlang 提倡一种称为面向并发编程的编程风格,在这种风格中,您将对象抽象为通过消息传递进行通信的独立进程。每个进程都有自己的本地状态,它们生活在自己的平行世界中。动态多态性是通过以下事实实现的:您可以定义一个 可以响应公共消息集 消息的进程。由于 Erlang 的“对象”存在于它们自己的微小进程中,因此它成为了对现实世界进行建模的自然媒介。在 Erlang 中,您可以比在任何其他语言中更好地利用您的 OOP 技能。

在这么小的篇幅里无法对 Erlang 中的 OOP 进行完整的描述。我建议你看书Programming Erlang: Software for a Concurrent World

另见这些链接:

【讨论】:

  • 我以为 Joe Armstrong 从未承认 Erlang 是一种 OO 语言。
  • @Jeffrey 我不知道 Joe Armstrong 是否承认 Erlang 是面向对象的,但如果你按照 OOP 的最严格定义,Erlang 是少数可以让你在该范式中编程的语言之一.
  • Joe 在最严格的 Alan Kay 意义上承认这一点,但绝对不是在更常见的类/对象/层次结构意义上,即 OOP 一词的通常含义。接受这里有一个十字架来抵御 OOP 的邪恶! :-)
【解决方案2】:

我会使用记录:

-record(post, {title, date_created, body, comments = []}).
-record(comment, {created_by, date_created, content}).

那么如果你想使用mnesia作为数据库:

Post = #post{title = "", body = "", date_created = erlang:universaltime()},
mnesia:transaction(fun() -> mnesia:write(Post) end).

添加评论:

Comment = #comment{created_by = "", content = "", date_created = erlang:universaltime()},
mnesia:transaction(fun() ->
    [Post] = mnesia:read(post, Title),
    PostWithNewComment = Post#post{comments = [Comment | Post#post.comments]},
    mnesia:write(PostWithNewComment)
end).

我还没有测试过代码,但这就是我要做的。我还假设每个标题都是独一无二的。

【讨论】:

  • 方法、私有状态等呢?
  • 也许可以创建一个模块并导出这些函数:post:save(Title, Body) -> ok | {错误,原因}。 post:save_comment(PostTitle, CommentBody, CreatedBy) -> ok | {错误,原因} ?我不确定你所说的私有状态是什么意思
  • @TP 问题是关于在 Erlang 中做 OOP。如何使用 Erlang 来模拟具有状态和方法的对象,同时对对象的用户隐藏细节? (当然,Erlang 中没有可变状态,但对象的用户不必知道它在内部是如何处理的)我认为在模拟真实对象方面,过程比记录更好。
  • 我不会考虑在 Erlang 中进行 OOP,因为它旨在成为一种函数式编程语言。要向用户隐藏详细信息,您可能希望创建一个新方法并返回一个对象,请查看 ets:new/2 (erlang.org/doc/man/ets.html#new-2)。如果你真的想做OOP,你应该阅读这个问题:stackoverflow.com/questions/1063497/hidden-features-of-erlang (inheritance and parameterized modules)
  • @Vijay,也许你误解了我的问题,我不打算在 Erlang 中做 OOP。我的意思是我的理解仅限于 OOP 的工作原理,我想知道如何在 Erlang 中做类似的事情,而不是严格意义上的 OOP 方式。
【解决方案3】:

您的示例并不能真正代表良好的 OO 风格。评论会出现在已发布的博客文章上,因此到那时您只需对发布评论的帖子 ID 进行某种引用即可。

对于 OO 编程,拥有某种将帖子和评论对象发送到的 BlogDb 对象会更有意义。评论对象需要知道它是对哪个帖子 ID 进行评论。您不应使用“new”运算符创建帖子和评论对象,而是 BlogDb 接口具有返回这些新实例的方法。

突然之间,您有了一种在 Erlang 中实现相同功能的可行方法。启动一个 gen_server,即 blog_db。做类似的事情

Post = myblog:post(Title, Body),
{ok, Result} = myblog:add_post(BlogDb, Post),
...

您不需要知道 Post 值的详细信息,因此它的构造方式隐藏在另一个模块中的“构造函数”中。

【讨论】:

  • 为什么人们总是评论问题中的例子有多糟糕?它旨在作为示例,仅供快速参考,以帮助任何人更好地理解问题,而不是某种“精心设计、模式化的示例”!
  • 因为精心设计的 OO 与“CO”非常相似。
【解决方案4】:

对我来说,OOP 仅意味着消息传递、本地保留和保护以及隐藏状态进程, 以及所有事物的极端后期绑定。

Alan Kay 和 Dan Ingalls 是 Smalltalk 的创建者。如果你看一下 Smalltalk,就会清楚他对消息传递的含义:一条消息被发送到某个接收器对象,如 aBumblebee.fly()。我已经使用 Smalltalk 开发了将近 10 年。我知道它是如何设计的。但是在 Erlang 中所做的是 fly(aBumblebee) ,其中 aBumblebee 也不是类的实例。

我不确定这一点,但是当您查看 Erlang 中的演员时,他们似乎也不交换消息。据我了解 Erlang 到目前为止,接收 { case { ... } } 构造是因为必须从某个列表中检索消息。没有其他方法可以将其发送给接收演员。

如果 Erlang 是面向对象的,那么也不需要这些 when-case 语句。它们是必需的,因为没有后期绑定。 Erlang 中有动态调用,是的。但是没有动态发送消息,这就是后期绑定的意义所在:要跳转的函数指针不是在编译时定义的,而是在运行时查找的。由于 Erlang 中的所有函数都是全局的,因此无论如何都不需要从某个类中查找。另外,我看不到 Erlang 中存在何种保护方式。如果没有类、模块或其他东西,你如何提供封装?作为记录,所有字段都是公开的。

【讨论】:

    猜你喜欢
    • 2023-03-21
    • 2015-09-13
    • 2011-11-16
    • 2010-09-18
    • 2018-08-02
    • 2010-11-04
    • 2014-02-23
    • 1970-01-01
    • 2016-03-03
    相关资源
    最近更新 更多