我应该将该方法添加为受保护的,为什么?

时间:2013-01-14 15:34:36

标签: ruby encapsulation

我想在find_items子类中覆盖Item`s UserItem方法。 我应该将该方法添加为protected还是private

我现在认为受保护的方法可以在子类中使用,而私有只能在它们所属的类中使用。

class Item
  def item_ids
    @ids ||= REDIS.zrevrange(key, 0, 100).map(&:to_i)
  end

  def items
    find_items
    item_ids.collect {|id| records.detect {|x| x.id == id}}.compact.map(&:content)
  end

protected
  def items_scope
    Item
  end

  def find_items
    items_scope.find(item_ids)
  end
end

class UserItem < Item
  def initialize(user)
    @user = user
  end
  # should I add it here?
protected
  # or here?
  def items_scope
    Item.where(user_id: @user.id).not_anonymous
  end
end

方法覆盖:

def find_items
  items_scope.where(id: item_ids)
end

2 个答案:

答案 0 :(得分:2)

Ruby中的语义与您可能习惯的不同。实际上,私人 表示您无法为方法明确指定接收器,但您可以 只要你没有指定接收者,也可以从派生类中使用它。因此

class A
  def bar; 42; end
  private :bar
end

class B < A
  def foo; bar; end
end

和B.new.foo工作正常。所以,Ruby中的private非常接近受保护 在其他OO语言中。我甚至不记得Ruby中受保护的内容;这个很 在Ruby中很少使用。

在您的示例中,我不会将private用于find_items。我会将其公开或将其转换为mixin(因为它不使用实例变量)

答案 1 :(得分:0)

如果要保留原始可见性,则必须使新的重写方法受到保护。如果不这样做,它将具有公众可见性:

class A
  protected
  def f; 'A'; end
end

class B < A
  def f; 'B'; end
end

class C < A
  protected
  def f; 'C'; end
end

A.new.f  #=> #<NoMethodError: protected method `f' called for #<A:0x007fa754bdd0a0>>
B.new.f  #=> 'B'
C.new.f  #=> #<NoMethodError: protected method `f' called for #<C:0x007fc4f19f2af0>>

最终,这取决于你,尽管保持原始方法的可见性可能是一个好主意,除非你有特殊的理由不这样做。