2

find_itemsサブクラスのItemのメソッドをオーバーライドしたいと思いますUserItemprotectedそのメソッドをまたはとして追加する必要があり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
4

2 に答える 2

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 言語の protected にかなり近いです。Ruby の protected が何であったかさえ覚えていません。Ruby ではめったに使用されません。

あなたの例では、find_items にプライベートを使用しません。public のままにするか、mixin にします (インスタンス変数を使用しないため)。

于 2013-01-14T15:44:19.967 に答える
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>>

最終的にはあなた次第ですが、特別な理由がない限り、元のメソッドの可視性を維持することをお勧めします。

于 2013-01-14T15:39:59.417 に答える