ruby - 从子对象引用父对象

标签 ruby oop recursion variable-assignment

假设您有一个 User 类:

class User
  attr_accessor :widgets
end

和一个小部件:

class Widget
  attr_accessor :owner
end

并且您将一些小部件分配给用户:

user = User.new
widget = Widget.new
widget.owner = user
widget2 = Widget.new
widget2.owner = user
user.widgets = [widget, widget2]

现在你有一个userwidgetsowner的递归。 user.inspect 为每个小部件显示相同的 user 引用一次,从而使输出变得困惑:

user.widgets.first.owner.widgets.first.owner
=> #<User:0x00000001cac820 @widgets=[#<Widget:0x00000001ca45f8 @owner=#<User:0x00000001cac820 ...>>, #<Widget:0x00000001c87a20 @owner=#<User:0x00000001cac820 ...>>]>                                      

如果我们将此数据结构简化为哈希,我们将拥有:

{ user:
    { widgets: [ { widget: ... },
                 { widget: ... } ]
    }
}

我们可以传递它而不是分配widget.owner,并且引用父user会很容易。

我想知道是否有一种方法可以通过子对象访问父对象,而无需将所有者分配给所有子对象,接口(interface)可以像这样工作:

user = User.new
widget = Widget.new
user.widgets = [widget]
widget.parent
# => #<User:... @widgets=[#<Widget:...>]>

最佳答案

您正在寻找的是一位定制作家。没有parent方法或 Object 上的等效方法或BaseObject类,因为实现它需要对象跟踪碰巧指向它的所有其他对象。不过,当您需要该功能时,自定义编写器可以使其简单且易于实现。

class Widget
    attr_accessor :owner
end

class User
  attr_reader :widgets

  def widgets=(widgets)
    @widgets = widgets
    widgets.each do |widget|
      widget.owner = self
    end
  end
end

user = User.new
widget = Widget.new
user.widgets = [widget]
widget.owner #=> #<User:... @widgets=[#<Widget:...>]>

请注意,此自定义编写器仅涵盖常规分配,例如 user.widgets = [widget] 。如果你想做类似 user.widgets << widget 的事情,新的小部件不会被分配所有者。如果您希望能够做到这一点,您必须 monkeypatch Array like this (不推荐),否则您必须创建 WidgetCollection可能继承自 Array 的类。这就是ActiveRecord::Associations做。说到这里,如果您碰巧使用 Rails,那么一定要考虑使用 ActiveRecord 来为您完成这一切。看起来您在问的是普通的旧 ruby ,所以我给您一个普通的 ruby 答案。

关于ruby - 从子对象引用父对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31150753/

相关文章:

c# - 参数过多的构造函数

c++ - 递归搜索 n 叉树中的元素

ruby-on-rails - 如何将 Ruby on Rails 网站预编译为生产模式?

ruby-on-rails - Ruby datetime 属性值未保存在 SQLite DB 中

ruby-on-rails - ruby 用于哈希中的每个键/值对

ruby-on-rails - ActiveModel 动态属性类型

objective-c - 在 NSObject 子类的自定义 init 方法中使用 self = [super init]

c# - 从另一个类访问公共(public) by​​te[] 数组

javascript - 如何将此递归函数转换为迭代函数?

c++ - 迷失在递归函数的证明中