protected.rb

    有关此示例,请查看 protected.rb 程序。在这里,我创建了一个名为 的 MyClass 对象和一个 MyOtherClass 对象 myotherob,并且 MyOtherClass 继承自 MyClass。我尝试将 myotherob 作为参数传递给 myob 的公共方法,shout

    但是 shout 方法在参数对象上调用 private 方法 priv

    1. def shout( anOb ) # calls a private method
    2. puts( anOb.priv( "This is a #{anOb.class} - hurrah" ) )
    3. end

    这将不能运行!Ruby 解释 priv 方法是私有的。

    同样,如果我反过来这样做 - 也就是说,通过将父类对象 myob作为参数传递,并在子类对象上调用方法 shout,我会得到同样的错误:

    1. myotherob.shout( myob )

    MyClass 类还有另一个公共方法,exclaim。这次会调用一个 protected 方法,prot

    1. def exclaim( anOb ) # calls a protected method
    2. puts( anOb.prot( "This is a #{anOb.class} - hurrah" ) )
    3. end

    现在,我可以将 MyClass 对象 myob 或 MyOtherClass 对象 myotherob 作为参数传递给 exclaim 方法,并且在调用 protected 方法时都不会发生错误:

    1. myob.exclaim( myotherob ) # This is OK
    2. myotherob.exclaim( myob ) # And so is this…

    不用说,这仅在两个对象(接收器和参数)共享相同的继承链时才有效。如果发送不相关的对象作为参数,则无论其保护级别如何,你都无法调用接收器对象所属类的方法。

    私有方法的重点在于它不能从它所属的对象作用域之外被调用。所以这将不起作用:

    send.rb
    1. class X
    2. private
    3. def priv( aStr )
    4. puts("I'm private, " << aStr)
    5. end
    6. end
    7. ob = X.new
    8. ob.priv( "hello" ) # This fails

    符号后面提供的任何参数(如字符串,”hello”)都以正常方式传递给指定的方法。

    可以说使用 send 获取私有方法的公共访问权通常不是一个好主意(否则,为什么你首先将该方法设为私有的),所以应谨慎使用或根本不使用…

    之前,我们通过将方法名称附加到类的名称后面来创建类方法(class method),如下所示:

    1. def MyClass.classMethod

    有一种“快捷”语法。这是个示例:

    class_methods3.rb
    1. def MyClass.methodA
    2. end
    3. class << self
    4. def methodB
    5. puts("b")
    6. end
    7. def methodC
    8. puts("c")
    9. end
    10. end
    11. end

    这里,methodAmethodBmethodC 都是 MyClass 的类方法;methodA 是使用我们之前使用的语法声明的:

    但是,使用实例方法的语法声明了 methodBmethodC

    def <methodname>

    1. class << self
    2. # some method declarations
    3. end

    这可能会让你想起用于声明单例类(singleton classe)的语法。例如,在 singleton_class.rb 程序中,你可能还记得我们首先创建了一个名为 ob 的对象,然后给它声明了一个自己的方法,blather

    1. class << ob
    2. def blather( aStr )
    3. puts("blather, blather #{aStr}")
    4. end
    5. end

    这里的 blather 方法是 ob 对象的单例方法(singleton method)。类似地,在 class_methods3.rb 程序中,methodBmethodC 方法是 self 的单例方法,而 self 恰好是 MyClass 类。我们可以类似地通过使用 << 后跟类名来从类定义之外添加单例方法,如下所示:

    1. class << MyClass
    2. puts( "d" )
    3. end
    4. end

    你可以嵌套(nest)方法(将一个方法嵌套在另一个方法中)。这为你提供了一种将长方法划分为可重用块的方式。因此,例如,如果方法 x 需要在几个不同的点进行 y 计算,则可以将 y 方法放在 x 方法中:

    nested_methods.rb

    嵌套方法默认在定义它们的作用域之外是不可见的。因此,在上面的示例中,虽然可以从 x 内部调用 yz,但是任何其它代码都不能调用它们:

    1. ob = X.new
    2. ob.z # <= error

    但是,当你运行一个包含嵌套方法的方法时,这些嵌套方法将被带入该方法之外的作用域内!

    nested_methods2.rb
    1. class X
    2. def x
    3. print( "x:" )
    4. def y
    5. print("y:")
    6. end
    7. def z
    8. print( "z:" )
    9. y
    10. end
    11. end
    12. end
    13. ob = X.new
    14. ob.x #=> x:
    15. puts
    16. ob.y #=> y:
    17. puts
    18. ob.z #=> z:y:

    最后一点,值得一提的是 Ruby 中的方法名称几乎总是以小写字符开头,如下所示:

    1. def fred

    但是,这只是一个习惯约定,而非必须的。也可以用大写字母开头的方法名称,如下所示:

    1. def Fred

    由于 Fred 方法看起来像一个常量(以大写字母开头),因此你需要在调用它时添加括号来告诉 Ruby,它是一个方法:

    method_names.rb
    1. Fred # <= Ruby complains "uninitialized" constant