为什么可以在 Ruby 中显式调用私有 class 方法?
Why can a private class method be explicitly invoked in Ruby?
正如我们所知,在 ruby 中不能使用显式接收者调用私有方法。但是当我定义一个 class 时,我可以通过 class 本身调用一个私有的 class 方法。
例如:
class A
private
def self.test
puts "hello,world!"
end
end
A.test => hello,world!
A.new.test NoMethodError: private method `test' called for #<A:0x007f80b91a10f8>
这与私有的定义相矛盾。谁能告诉我原因。提前致谢!
def self.test
声明了一个 class 方法 ,而不是实例方法。要使 class 方法私有,您需要使用 private_class_method
,而不是 private
。
private
只影响实例方法。要创建私有 class 方法,请使用 private_class_method
:
class A
private_class_method def self.test
puts "hello,world!"
end
end
或
class A
def self.test
puts "hello,world!"
end
private_class_method :test
end
编辑: 另一种方法是在 metaclass 上定义方法 - 它们将表现为 class 方法。
class A
class << self
private
def test
puts "hello,world!"
end
end
end
不幸的是,没有 protected_class_method
这样的东西 - 但最后一个选项给了我们如何做的提示:
class A
class << self
protected
def test
puts "hello,world!"
end
end
end
但请注意,它只能从后代 class 的 class 方法中调用:
class B < A
def self.test_class
A.test
end
def test_instance
A.test
end
end
B.test_class
# => hello,world!
B.new.test_instance
# => `test_instance': protected method `test' called for A:Class (NoMethodError)
正如我们所知,在 ruby 中不能使用显式接收者调用私有方法。但是当我定义一个 class 时,我可以通过 class 本身调用一个私有的 class 方法。
例如:
class A
private
def self.test
puts "hello,world!"
end
end
A.test => hello,world!
A.new.test NoMethodError: private method `test' called for #<A:0x007f80b91a10f8>
这与私有的定义相矛盾。谁能告诉我原因。提前致谢!
def self.test
声明了一个 class 方法 ,而不是实例方法。要使 class 方法私有,您需要使用 private_class_method
,而不是 private
。
private
只影响实例方法。要创建私有 class 方法,请使用 private_class_method
:
class A
private_class_method def self.test
puts "hello,world!"
end
end
或
class A
def self.test
puts "hello,world!"
end
private_class_method :test
end
编辑: 另一种方法是在 metaclass 上定义方法 - 它们将表现为 class 方法。
class A
class << self
private
def test
puts "hello,world!"
end
end
end
不幸的是,没有 protected_class_method
这样的东西 - 但最后一个选项给了我们如何做的提示:
class A
class << self
protected
def test
puts "hello,world!"
end
end
end
但请注意,它只能从后代 class 的 class 方法中调用:
class B < A
def self.test_class
A.test
end
def test_instance
A.test
end
end
B.test_class
# => hello,world!
B.new.test_instance
# => `test_instance': protected method `test' called for A:Class (NoMethodError)