Ruby包含对象的最佳实践

时间:2015-01-29 13:22:57

标签: ruby oop

首先,大家好,

我想了解ruby中的对象包含最佳实践。 让我们来描述一下背景:

  • 对象A是" root"对象
  • 对象B是一个独立的对象,但需要访问A属性。所以要初始化它,我做" B.new(instance_of_A,other_param)"我将A的实例存储在attr_accessor
  • 对象C是一个独立的对象,但需要访问B属性。所以,我使用相同的方式初始化它(传递B的实例)

结果是我最终得到了非常大的嵌套对象并重复了自己。

是否还有其他解决方案/模式可以做得更好但是更清洁? 这类实施有什么好的例子吗?

谢谢!

这是一个基本的例子,但是想象一下这个对象有很多属性的方式。

require 'awesome_print'

class A
  attr_accessor :title

  def initialize(title)
    @title = title
  end
end

class B
  attr_accessor :a, :level

  def initialize(a, level)
    @a = a
    @level = level

    # Here, I need to access to a.title
  end
end

class C
  attr_accessor :b, :name

  def initialize(b, name)
    @b = b
    @name = name

    # Here, I need to access to b.level
  end
end

a = A.new 'test'

b1 = B.new a, 1
b2 = B.new a, 2
b3 = B.new a, 3

c1 = C.new b1, 'one one'
c2 = C.new b1, 'one two'
c3 = C.new b1, 'one three'

ap c1
ap c2
ap c3

c4 = C.new b2, 'two one'
c5 = C.new b2, 'two two'
c6 = C.new b2, 'two three'

# ... etc

结果对我来说似乎很脏(在其他大对象中包含大对象)

#<C:0x000001011e9680 @b=#<B:0x000001011e9720 @a=#<A:0x000001011e9748 @title="test">, @level=1>, @name="one one">
#<C:0x000001011e9630 @b=#<B:0x000001011e9720 @a=#<A:0x000001011e9748 @title="test">, @level=1>, @name="one two">
#<C:0x000001011e95b8 @b=#<B:0x000001011e9720 @a=#<A:0x000001011e9748 @title="test">, @level=1>, @name="one three">

1 个答案:

答案 0 :(得分:0)

关于面向对象的是你封装数据,方法以及其他对象以创建抽象。更多的抽象可以使您更容易推理您的项目,但它也增加了复杂性并使您的项目更复杂。我特别发现很难平衡这两者。这只需要经过多年的实践。

如果三个封装级别看起来太多,请尝试查看dependencies as a code smell

所有对象都代表一个有意义的,有用的抽象吗?例如:

  • B似乎正在使用A#title作为
  • B公开A以供C使用
  • B公开level以供C使用

在这里,B似乎只是采用A并包含一个level属性,因此它可以被C使用。这种抽象是否意味着有用的东西?

如果C收到A对象levelname,我们可以简化问题吗?

class A
  attr_reader :title # Do you really need outside code to change this?

  def initialize(title)
    @title = title
  end
end

class C
  attr_reader :level, :name

  def initialize(a, level, name)
    @a = a
    @level = level
    @name = name

    # Here, you access a.title to do whatever you did in B
  end

  def title
    @a.title
  end
end