【问题标题】:"Parent", "Child" Classes In Ruby (Not Inheritance)Ruby 中的“父”、“子”类(不是继承)
【发布时间】:2016-11-15 18:17:06
【问题描述】:

假设我有两个班级。一个班级,“父母”,有许多另一个班级“孩子”。这不是继承,我不希望父方法作用于子对象。我想要的是子对象能够引用父对象,从中获取变量(child.parent.var)并调用修改父对象的父方法(child.parent.update)。

我希望一个对象(它可以被认为是一个子对象,但不是子对象,因为这不是继承)在初始化时传递一个对另一个对象的引用。我会将其与数据库中的父子关系进行比较,在该数据库中,我们将信息存储在父级上,因此我们不必将其复制到每个子级。

例子:

class Parent
    attr_accessor :var

  def initialize(num)
    @var = num
  end

  def increase
    @var += 1
  end
end

class Child
    attr_accessor :var, :parent

    def initialize(parent, num)
        @parent = parent
        @var = num
    end

    def sum
        @parent.increase
        @parent.var + var
    end
end

parent1 = Parent.new(1)

child1 = Child.new(parent1, 2)
child2 = Child.new(parent1, 3)

child1.parent.increase # update the parent variable
child2.parent.var      # get the parent variable

上面的代码确实有效,但是有没有更好(更简洁,或者更 ruby​​-esq)的方法来实现这一点?

非常感谢您的帮助/想法。

【问题讨论】:

  • 欢迎来到 Stack Overflow。这是一个非常棒的初学者问题。将来,请尝试更多地描述您的问题的详细信息。 “感觉很奇怪”是一个非常模糊的描述。也就是说,虽然 Stack Overflow 最近倾向于硬代码问题,但设计和代码结构问题仍然是这里的主题。请务必描述您的实际问题。通常,softwareengineering.stackexchange.comcodereview.stackexchange.com 也是解决这类问题的好地方。
  • @Holger 只是在引用其他网站时,指出cross-posting is frowned upon 通常会有所帮助
  • @HolgerJust 感谢您的智慧,我的朋友!仍然是新手,所以我会在下一个问题上听取您的建议:-)
  • 您的问题不清楚。您问题的重要一点似乎是:“由于 ruby​​ 是通过引用传递的,那么处理这个问题的正确方法是什么?”但是,您的前提不正确:Ruby 严格按值传递,从不按引用传递,因此这似乎使您的整个问题无效。
  • @JörgWMittag 虽然 Ruby 确实是按引用值传递的,但这个问题并没有受到这个稍微不正确的假设的影响。关于如何构造引用和访问其他对象的类的要点仍然存在。

标签: ruby object-oriented-analysis


【解决方案1】:

这基本上就是应该如何完成的 :) 不过,有几个可能的改进,具体取决于您实际想要实现的目标。

现在,您的 Child 实例在其外部接口上公开对父级的访问(通过公共 parent 访问器)。这通常违反了Law of Demeter,它规定对象只能与其直接邻居对话。从这个意义上说,parent 在通过子对象访问时是陌生的。

您可以通过隐藏父对象来改进您的设计:

class Child
  extend Forwardable

  def_delegator :@parent, :var, :parent_var
  def_delegator :@parent, :increase

  attr_accessor :var

  def initialize(parent, num)
    @parent = parent
    @var = num
  end

  def sum
    @parent.increase
    @parent.var + var
  end
end

在这里,我们使用 Ruby 的Forwardable 模块来提供从客户端访问父级的一些方法。这使得这些方法成为您的 Child 类的单个公共接口的一部分。

parent = Parent.new(1)

child = Child.new(parent, 2)

child.var
# => 2
child.parent_var
# => 1
child.increase
# => 2
parent.var
# => 2
# ^^^^ the increase method was called on the parent object

从外部看,转发方法并不重要,您可以稍后更改它,而完全不会影响您的外部接口。


第二个改进可能是扩展您的 Parent 类以直接生成子级:

class Parent
  # ...

  def child(num)
    Child.new(self, num)
  end
end

这通常称为Factory Method,即构建其他对象的方法。这样,您可以隐藏构建子对象并将它们附加到父对象的复杂性。

你可以这样称呼它

parent = Parent.new(1)
child = parent.child(2)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-11
    • 2014-01-21
    相关资源
    最近更新 更多