2013-01-14 34 views
2

我想重写UserItem子类中的Item find_items方法。 我应该将该方法添加为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

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

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

class B < A 
    def foo; bar; end 
end 

和B.new.foo工作得很好。因此,Ruby中的私有文件在其他OO语言中相当接近受保护的 。我甚至不记得Ruby中的保护是什么;在Ruby中很少使用的是 。

在你的例子中,我不会使用private作为find_items。我会公开它或将它变成mixin(因为它不使用实例变量)

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>> 

归根结底,这是给你的,虽然它可能是一个好主意,除非你有特殊原因不能保持原有方法的可见性。

相关问题