Post

Ruby类的public private protected

public method

1
2
3
4
5
6
7
8
9
class Book
  def name
     "name"
  end
end

book = Book.new
puts book.name

1
name

public是默认的方式,可以以实例化的方式通过.号来进行访问, 可以被定义它的类和其子类访问,可以被类和子类的实例对象调用

private method

1
2
3
4
5
6
7
8
9
class Book
  private
  def private_name
    "private_name"
  end
end

book = Book.new
puts book.private_name
1
2
3
4
5
 13:in `<main>': private method `private_name' called for an instance of Book (NoMethodError)

 puts book.private_name
          ^^^^^^^^^^^^^
 Did you mean?  private_methods

可以看见,在外部是无法去直接访问private method的

1
2
3
4
5
6
7
8
9
10
11
12
13
class Book
  def show_private
    private_name
  end

  private
  def private_name
    "private_name"
  end
end

book = Book.new
puts book.show_private
1
private_name

要想访问private method,必须在类的内部直接引用private method,而不能在任何外部以实例的方式去引用

private和self的关系

在网上很多几乎,几乎我看到过的,全都在说private的一个特点就是只能在内部直接使用,不能通过.来调用,甚至self都不行,这里我要证实一下,其实这是个天大的谣言!!! 按照官方说法其实是private是不能指定显示的receiver,也就是不能显示指定调用者,必须要通过默认的调用者,也就是self,所以其实通过self.private是没有问题的, 是不是这样的直接证实一下就行

1
2
3
4
5
6
7
8
9
10
11
12
13
class Book
  def show_private
    self.private_name
  end

  private
  def private_name
    "private_name"
  end
end

book = Book.new
self.puts book.show_private
1
private_name

可以看出确实是正确输出了,另外,puts也是private method,用self.puts也是能正确输出的,事实再次证明,一定一定不要去完全相信网上的东西,只有权威的官方文档才是唯一值得信赖的

protected

关于protectedprivate的区别是非常晦涩,感觉很不好说清楚,这里直接举几个例子来演示可能会更好的理解

1
2
3
4
5
6
7
8
9
class Book
  protected
  def protect_name
    "protected_name"
  end
end

book = Book.new
puts book.protect_name
1
2
3
4
2.rb:19:in `<main>': protected method `protect_name' called for an instance of Book (NoMethodError)
puts book.protect_name
         ^^^^^^^^^^^^^
Did you mean?  protected_methods

: 从这个层面来讲,protecedprivate是一样的,在外部,均不能被类的实例对象直接调用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Book
  protected
  def protect_name
    "protected_name"
  end
end

class Comic < Book
  def display
     Book.new.protect_name
  end
end

puts Comic.new.display
1
protected_name

这里新建一个Comic类继承于Book类,注意,这里开始就有差别了,这里Book的子类Comic里调用了Book类的实例来访问这个protected的方法,这里是没有报错的,正确输出方法结果,所以,protected方法是可以在类和子类里的实例进行访问的,前面举的例子我刻意强调在类的外部protected是无法调用的,但是在内部它可以调用,这里可以再次验证下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Book
  protected
  def protect_name
    "protected_name"
  end
end

class Comic 
  def display
     Book.new.protect_name
  end
end

puts Comic.new.display
1
2
3
4
5
3.rb:11:in `display': protected method `protect_name' called for an instance of Book (NoMethodError)
     Book.new.protect_name
             ^^^^^^^^^^^^^
 Did you mean?  protected_methods
        from 3.rb:16:in `<main>'

这里仅仅是把Comic类设置成独立的类,不是继承于Book了,所以内部是会报错了,这里还可以去验证private是否可以用内部实例去访问,就不再演示了,private是无法跟protected一样可以在内部通过实例去访问的

小结

经过演示验证,可以得出结果,private只能通过默认self的方式在类的内部进行调用,具有最高的访问权限,因此对于一些完全不想暴露的方法,如果只是在类的内部进行调用,就可以用private方法。而protected在一定程度上具有跟private类似的效果,但是protected可以在类以及子类的内部进行实例化访问,因此protected可以在一些需要内部继承的调用,又不想完全暴露的需求上使用。

Ruby相关文章

1. Ruby类基础

2. 类的public private protected

3. Ruby yield

4. Ruby双冒号

This post is licensed under CC BY 4.0 by the author.