今天來談談方法的可見性:公用(public)、受保護(protected)、私用(private)。
我們先來看看這三種不同的方法都寫在什麼位置:
class ClassName
#公用(public)的方法都在這裡!
def method_1
end
#下面是受保護(protected)的方法
protected
#受保護(protected)的方法都要放在這裡!
def method_2
end
#下面是私用(private)的方法
private
#私用(private)的方法都要放在這裡!
def method_3
end
end
也可以這麼寫:
class ClassName
def method_1
end
def method_2
end
def method_3
end
protected :method_2
private :method_3
end
兩個範例都可以看得出,method_1
是public的方法,method_2
是protected的方法而method_3
則是private的方法,那這些方法的作用跟規定是什麼呢?
class Test
def initialize(test=5566)
@test = test
end
def greeting
puts "Hi Hi"
end
end
yo = Test.new
=> #<Test:0x007f852c890900 @test=5566>
yo.greeting
=> "Hi Hi"
yo.initialize
NoMethodError: private method `initialize' called for #<Test:0x007f852c890900 @test=5566>
噴錯的訊息很明顯指出initialize是private method,所以不可以像一般public方法直接被實體物件調用。
上面我們定義了一個方法為i_love_ruby
,這個方法沒有被某個自定的類別給封裝起來,我們利用Object.private_instance_methods
找到了所有屬於Object的私用實體方法,其中也包含了我們自己幫他新定義的i_love_ruby
方法。
class RubyGirl
def say_hello
puts self.my_age
end
private
def my_age
"Hi, I'm 18 years old!"
end
end
請注意!上方程式碼有錯誤之處!我們把my_age
方法定義成private的方法,所以這個方法可以照上述第一點,被類別內部使用。因此可以看到say_hello
的方法中,我們有呼叫到my_age
,但這寫法有誤,my_age
會自動在self上進行,因此前面不需要再加上self.,下方程式碼才是正確的:
class RubyGirl
def say_hello
puts my_age
end
private
def my_age
"Hi, I'm 18 years old!"
end
end
annie = RubyGirl.new
=> #<RubyGirl:0x007ff3b233df30>
annie.my_age
NoMethodError: private method `my_age' called for #<RubyGirl:0x007ff3b233df30>
annie.say_hello
=> "Hi, I'm 18 years old!"
好的,我們最後用一個例子來統整這三個方法:
class RubyGirl
def greeting
"Hi, I'm #{self}"
end
def say_my_email
"This is my email: #{self.email}"
end
def say_my_age
"This is my age: #{age}"
end
protected
def email
"rubygirl@ruby.me"
end
private
def age
18
end
end
annie = RubyGirl.new
=> #<RubyGirl:0x007fe039a06150>
annie.greeting
=> "Hi, I'm #<RubyGirl:0x007fe039a06150>"
#greeting屬於public方法,可供該類別的實體物件調用。
annie.email
NoMethodError: protected method `email' called for #<RubyGirl:0x007fe039a06150>
#email屬於protected方法,只能在類別裡面供實體方法調用。
annie.age
NoMethodError: private method `age' called for #<RubyGirl:0x007fe039a06150>
#age屬於private方法,只能在類別裡面供實體方法調用。
annie.say_my_email
=> "This is my email: rubygirl@ruby.me"
#注意最上面的方法定義中是寫self.email,這裡也可以改成email,protected方法比較彈性。
annie.say_my_age
=> "This is my age: 18"
#注意上面的方法定義中是寫age,這裡千萬不能加上self.,private方法不能加上self.。
22天了,今天的主題也有點容易搞混呢,希望大家看得不會霧煞煞,有哪裡有問題請一定要跟我說,乾蝦!
The wisest mind has something yet to learn.
想學的東西還有好多,只有30天根本不夠,看到有位前輩明明已經達成30天鐵人賽,卻還繼續寫,真的非常佩服啊!
延伸閱讀:Public, Protected and Private Method in Ruby-高見龍 ,這篇文章很受用,能理解如何在子類別中調用父類別的protected與private方法喔!