我对private和protected这两个词感到困惑。我读到过,在类之外创建的对象上调用private和protected方法是不可能的。我可以在public方法中使用它们。那么,为什么这段代码可以使用protected,而不是private呢?
class Student
def initialize(name, grade)
@name = name
@grade = grade
end
def better_grade_than?(other_student)
grade > other_student.grade ? true : false
end
protected
def grade
@grade
end
end
class Joe < Student
end
class Bob < Student
end
joe = Joe.new('Joe', 88)
bob = Bob.new('Bob', 60)
puts joe.better_grade_than?(bob) # true
puts bob.better_grade_than?(joe) # false
如果是private,则会输出NoMethodError。
2条答案
按热度按时间lc8prwob1#
在Ruby中,
protected
方法可以被定义它的类和以及继承它的类访问。另一方面,private
方法只能被定义它的类访问。在你的例子中,
protected
可以工作,因为Joe和Bob都继承了Student,所以他们可以使用它的保护方法。gfttwv5a2#
我读到过在类外部创建的对象上调用private和protected方法是不可能的。
这是不对的。
第一个月
private
意味着“只能由消息发送调用,该消息发送具有self
的隐式接收者或具有作为字面伪变量关键字self
的显式接收者”。换句话说,
private
方法qux
只能通过消息发送调用,如下所示:或类似于:
它 * 不能 * 与 * 任何其他接收器 * 一起调用 。即使
self
作为接收器也不行, 除非 * 它是实际的、字面的伪变量关键字self
:你可以自己试试:
我不知道你是从哪里读到你引用的声明的,但我建议你总是阅读官方来源。
这就是13.3.5.3ISO/IEC 30170:2012 Information technology — Programming languages — Ruby specification的www.example.com Private methods 部分所要说明的内容,例如:
13.3.5.3私有方法
私有方法是其可见性属性设置为私有可见性的方法。
私有方法不能用显式接收器调用,即,如果 primary-expression 或 chained-method-invocation 出现在与方法调用中的方法接收器对应的位置,则私有方法不能被调用,但以下任何形式的方法调用除外,其中 primary-expression 是 self-expression。
请注意,ISO Ruby编程语言规范自2012年以来一直没有更新,所以这是一个稍微过时的定义。该规范在几年前稍微简化了一下。现在,第二段可能应该读起来更像这样:
私有方法不能用显式接收器调用,即,如果 primary-expression 或 chained-method-invocation 出现在对应于方法调用中的方法接收器的位置,则私有方法不能被调用,但 primary-expression 是 self-expression 的方法调用除外。
但请注意,这在这里没有区别,因为在代码中,无论如何都不会使用 * 自我表达 * 作为接收器,所以 * 自我表达 * 是在有限数量的情况下允许还是始终允许是无关紧要的。
private
和message sends的ruby/spec似乎也不是完全最新的,但同样,这些差异对您的问题并不重要。然而,Modules的RDoc,特别是关于可见性的小节,是完全最新的,而且非常清楚:
第三个可见性是private。private方法只能从拥有者类别内部呼叫,而不需要接收者,或以常值
self
做为接收者。如果呼叫private方法时使用的接收者不是常值self
,则会引发NoMethodError
。protected
型protected
表示“只能由从发送方发送的消息调用,该发送方是定义该方法的模块的示例”。换句话说,如果在模块
M
中定义了protected
方法m
,如下所示:则
m
只能由消息send调用,其中发送方是M
的示例:我 * 认为 * 一个简洁的方式来表达测试将是这样的:
以下是13.3.5.4ISO/IEC 30170:2012 * 信息技术-编程语言- Ruby* 规范的www.example.com * 受保护的方法 * 部分的内容:
13.3.5.4受保护方法
受保护的方法是其可见性属性设置为受保护的可见性的方法。
当且仅当满足以下条件时,才可以调用受保护的方法:
Module
的示例,其中存在该方法的绑定。如果 M 是单例类,则可以通过实现定义的方式来确定该方法是否可以被调用。
以及RDoc:
第二个可见性是
protected
。调用受保护的方法时,发送方必须继承定义该方法的Class
或Module
。否则将引发NoMethodError
。受保护的可见性最常用于定义
==
和其他比较方法,在这些方法中,作者不希望将对象的状态公开给任何调用方,而希望将其仅限制为继承的类。那么,为什么这段代码适用于protected而不是private呢?
它不适用于
private
,因为这里发送的消息的显式接收者不是文本伪变量关键字self
:接收方为
other_student
,但如果grade
为private
,则只能由消息发送调用,消息发送使用隐式接收方(grade
)或显式接收方self
(self.grade
)。因为
other_student
是Student
的一个示例,所以它 * 确实 * 适用于protected
。