protectedとprivateメソッドの可視性
基本的なルールは以下
protected
- レシーバーなしで参照可能
- レシーバー(自分またはサブクラス)から参照可能
- 自クラス、サブクラスから参照可能
- クラス外部からは参照できない
private
- レシーバーなしで参照可能
- レシーバーから参照できない
- 自クラス、サブクラスから参照可能
- クラス外部からは参照できない
class C def internal_use_private_and_protected protected_method # 呼び出し可 private_method # 呼び出し可 end def internal_use_private_and_protected_with_reciever self.protected_method # 呼び出し可。自クラスから呼び出し可。 self.private_method # 呼び出し不可。レシーバーから呼び出せない。 end def use_protected(other) other.protected_method # 自クラス、サブクラスなら呼び出し可。 end protected def protected_method puts "protected_method" end private def private_method puts "private_method" end end class D < C end c = C.new # 外部から直接呼び出し不可 c.protected_method #=> NoMethodError: protected method `protected_method' called for # 外部から直接呼び出し不可 c.private_method #=> NoMethodError: private method `private_method' called for # レシーバーなしでは両方呼び出し可 c.internal_use_private_and_protected #=> protected_method #=> private_method # レシーバーあり(自クラス)ではprotectedのみ呼び出せる c.internal_use_private_and_protected_with_reciever #=> protected_method #=> NoMethodError: private method `private_method' called for d = D.new # サブクラスから呼び出し可 d.use_protected(d) #=>protected_method
メソッドの可視性変更
子クラスで再定義した場合、子クラスのメソッドが優先される。可視性の変更も可能
class C protected def protected_method puts "protected_method" end private def private_method puts "private_method" end end class D < C #表示内容の変更と可視性をpublicへ変更 def protected_method puts "edit protected_method" end #表示内容の変更と可視性をpublicへ変更 def private_method puts "edit private_method" end end d = D.new d.protected_method # =>edit protected_method d.private_method # =>edit private_method
open-uriとopen
http/ftpに簡単にアクセスするためのクラス
require 'open-uri' open("http://www.ruby-lang.org/") { |f| # 開いたファイルオブジェクトはStringIOまたはTempfile f.each_line { |line| p line } # OpenURI::Metaモジュールで拡張されているため、メタ情報取得メソッドが使用可能 p f.base_uri # <URI::HTTP:0x40e6ef2 URL:http://www.ruby-lang.org/en/> p f.content_type # "text/html" p f.charset # "iso-8859-1" p f.content_encoding # [] p f.last_modified # Thu Dec 05 02:45:02 UTC 2002 }
環境変数のEnv
keyと値には文字列しか使えない。
ENV[1] = "A" Exception TypeError at (irb):16 - no implicit conversion of Fixnum into String ENV['A'] = 1 Exception TypeError at (irb):17 - no implicit conversion of Fixnum into String ENV['A'] = "TEST" => "TEST"
hashと同様のインターフェースをもつが、hashではない。
ENV.class => Object
pとprintの裏で使われているメソッド
p は inspectメソッド
print は to_sメソッド
で表示している。
Object#to_s と Object#to_strの違い
to_sは明示的な変換。printや文字列展開で使われている。
to_strは暗黙的な変換。文字列の+演算子利用時に呼び出される。
class Person attr_reader :name def initialize(name) @name = name end def to_str @name end end class NotStringPerson attr_reader :name def initialize(name) @name = name end def to_s @name end end tanaka = Person.new("tanaka") suzuki = NotStringPerson.new("suzuki") # + 演算子利用時に暗黙的に to_str を利用した変換が行われる puts "■ + 演算子利用時の to_str 呼び出し確認" puts "tanaka name = " + tanaka begin puts "suzuki name = " + suzuki rescue => e puts e.message end # 変数展開時にも暗黙的に to_s を利用した変換が行われる puts "■ 変数展開" puts "tanaka name = #{tanaka}" puts "suzuki name = #{suzuki}"
出力結果
■ + 演算子利用時の to_str 呼び出し確認 tanaka name = tanaka no implicit conversion of NotStringPerson into String #to_strなし ■ 変数展開 tanaka name = #<Person:0x2bcd370> #to_sなし suzuki name = suzuki
ensure 節あるときの評価値
下記の評価値はどうなるか?
def m begin 1 rescue 2 else 3 ensure 4 end end p m
答えは「3」まじか。。
下記のような仕様らしい。
本体、rescure節、else節のうち最後に評価された文の値がbegin式全体の評価値。
ensure節は実行されるが、評価値としては無視される。
メソッド内で定数を更新
下記でエラーになる二つは??
X = 'abc' def m X # (1) X = 'def' # (2) X += 'def' #(3) X << 'def' # (4) end
答えは(2),(3)らしい。
メソッド内で定数を更新(定義 =で代入)するとSyntaxError発生。
<<は破壊的でないので、OKらしい。へーー。
参考URL
徒然なるままに|Rubyにおけるメソッドの可視性(public, private, protected)について
library open-uri (Ruby 1.8.7)
武田哲也さんのRuby技術者認定試験受験記 - Togetterまとめ
Ruby | 文字列への明示的変換と暗黙的変換。Object#to_s , Object#to_str の使い分け - Qiita
制御構造 (Ruby 2.1.0)