Rubyのオブジェクト指向のアプローチによるプログラミング学習雑学
開講クラス
StringやArrayのような標準的なライブラリのクラスであっても、既存のクラスを再度オープンして動的に変更することが可能です。このような動作をオープンクラスと呼びます。
モンキーパッチ
あるクラスに不用意に新しい機能を追加して、そのクラスの本来の機能を上書きし、それがコードの他の部分に影響を与える場合、そのようなパッチはモンキーパッチと呼ばれます。
クラスとモジュール
Ruby の class キーワードは、型宣言文というよりもスコープ演算子です。class キーワードの核となるタスクは、クラスのコンテキストに入り込み、その中でメソッドを定義できるようにすることです。
すべてのクラスはモジュールであり、クラスは、クラスの継承構造を整理し、オブジェクトを作成する3つのメソッド(new、allocate、superclass)を備えた拡張モジュールです。
Rubyにおけるクラスとモジュールの概念は、互いに置き換えられるほど近いものであり、両方を維持する理由は、コードを明確にし、コードの意図をより明確にするためである。使い分けの原則です。
- 自分のコードを他のコードに含める場合は、モジュールを使用する必要があります。
- コードの一部をインスタンス化または継承させたい場合は、クラスを使用する必要があります。
- モジュール機構は、他の言語で見られるような名前空間の概念を実装するために使用することができます。
Rubyの::記法
Ruby における定数のパス (スコープ) は、ファイルシステムにおけるディレクトリと同様に :: で分割されてアクセスされ、デフォルトでは変数のパスのルート位置を示すために直接 :: で始まります (例 ::: Y)。
オブジェクトとは
オブジェクトは、インスタンス変数とそのクラスへの参照のセットです。オブジェクトのメソッドは、オブジェクト自体にはなく、オブジェクトのクラスに存在します。
クラスとは
クラスはオブジェクト(Classクラスのインスタンス)とインスタンスメソッドのセットとそのスーパークラスへの参照です。ClassクラスはModuleクラスのサブクラスであり、クラスはモジュールでもあります。
loadメソッドとrequireメソッドの類似点・相違点
loadとrequireはどちらも他人のコードをインポートするために使うことができます。違いは、loadメソッドはコードの読み込みに使われ、現在の名前空間を汚したくない場合は、明示的にload('file.rb',true)で匿名モジュールを作成してもらい、file.rbの定数を引き継ぐ必要があり、requireはライブラリの読み込みに使われる点です。また、loadメソッドは呼び出されるたびに読み込まれたファイルを再度実行しますが、requireは各ライブラリファイルを一度だけ読み込みます。
プリペンド、インクルード、祖先の連鎖
クラスとモジュールは親子関係なので、祖先チェーンはモジュールを含むことができ、prepend と include はそれぞれモジュールをチェーンに追加できますが、違いは include メソッドが呼ばれたとき、モジュールは現在のクラスの真上の祖先チェーンに挿入され、prepend も祖先チェーンに挿入される一方、他の位置はです。
プライベートルール
プライベートメソッドは、明示的にアクセプタを指定して呼び出すことはできません。プライベートメソッドは暗黙の受信者である自分からしか呼び出すことができない(Object#sendは例外)
自己関連
メソッドが呼び出されたとき、アクセプタは self の役割を果たす 明示的にアクセプタを指定しないメソッド呼び出しは self への呼び出しとして扱われる モジュール(またはクラス)が定義されたとき、そのモジュール(またはクラス)は self の役割を演じる。
オブジェクト、クラス、モジュール間の関係
上のModule.classもClassを指しており、上のボックスの中身はすべてClassだが、その親子構成はsuperclassによって確立されており、相違点や類似点があり、それはClass.ancestorsで確認できると解釈できる。
動的なメソッド
メソッドを動的に呼び出す
Ruby では、Object#send メソッドを使用すると、ポイント識別子ではなく、オブジェクトの指定されたインスタンスメソッドを呼び出すことができます。
コード例
class MyClass
def my_method(my_arg)
my_arg * 2
end
end
obj = MyClass.new
obj.my_method(3) #=> 6
obj.send(:my_method, 3) #=> 6
上記のコードは、直接呼び出しても、sendメソッド呼び出しを使用しても、同じ結果になります。sendを使う利点は、メソッドコールをコーディングの中で動的に決定できることです。このテクニックはメタプログラミングではダイナミックディスパッチとして知られています。
もう1つのポイントは、Object#sendでは、オブジェクトのパブリックメソッドだけでなく、プライベートメソッドも呼び出せるということです。オブジェクトのカプセル化された性質を維持し、プライベートなメソッドを外部に公開したくない場合は、Object#public_send メソッドを使用できます。
メソッドを動的に定義する
Ruby では、メソッドの動的な呼び出しの他に、Module#define_method メソッドとコードブロックによって動的なメソッドを定義する方法が用意されています。
サンプルコード
class MyClass
define_method :my_method do |my_arg|
my_arg * 3
do
end
obj = MyClass.new
obj.my_method(2) #=> 6
上記のコードでは、キーワード def を define_method メソッドに置き換えています。define_method メソッドは、定義できる方法がもう少し柔軟で、関数の定義もコード内で派生して行うことができ、実装に柔軟性を持たせていることを除いて、基本的に同じです。
method_missing メソッド
method_missing メソッドは厳密には定義されていませんが (メソッド一覧には現れません)、本質的にはメソッド検索機構であり、呼び出しを横取りして適切なメソッドに妥当な応答を与えるものです。これは、例外処理で例外を投げるのと同じようなもので、一度に1つのレイヤーを処理するものです。
method_missing は、オブジェクトがメソッドを呼び出すときに、対応するクラスのインスタンスメソッドを探し、見つからなければ BasicObject クラスを見つけるまで祖先の連鎖を探すというメカニズムを使っています。もし見つからなければ、最終的にBasicObject#method_missingが呼び出され、NoMethodError例外がスローされます。
似たようなメソッドをたくさん定義する必要があるときは、method_missingメソッドをオーバーライドして、似たようなメソッドに一様に対応し、すでに定義されているメソッドを呼び出すように動作させることができる。
コード例
class Roulette
def method_missing(name, *args)
person = name.to_s.capitalize
super unless %w[Bob Frank Bill Honda Eric].include? person
number = 0
3. times do
number = rand(10) + 1
puts "#{number}... "
end
"#{person} got a #{number}"
end
end
number_of = Roulette.new
puts number_of.bob
puts number_of.kitty
動的プロキシ
method_missingを通してカプセル化されたオブジェクトへの呼び出しを集め、それらの呼び出しをカプセル化されたオブジェクトに転送するプロセスは、method_missingがダイナミックで、転送がプロキシである、ダイナミックプロキシと呼ばれます。
const_missing メソッド
method_missing と同様に、定数に関する const_missing メソッドも存在します。存在しない定数を参照するとき、Ruby は定数名をシンボルとして const_missing メソッドに渡します。
ホワイトボードクラス(白紙状態)
メソッドがほとんどないクラスを白紙クラスと呼びますが、BasicObjectクラスを継承することですぐに白紙クラスを手に入れることができます。この方法以外にも、メソッドを削除することで、通常のクラスを白紙クラスに変更することも可能です。
deleteメソッド
メソッドを削除するには、2つの方法があります。
- モジュール#undef_method
- モジュール#remove_method
この2つの違いは、Module#undef_methodはすべての(継承されたものも含む)メソッドを削除することです。Module#remove_method は継承されたメソッドを維持したまま、受信者自身のメソッドだけを削除します。
Method_missing を使用した動的メソッドの使用原則
できる限りダイナミックメソッドを使用する。method_missing メソッドは、必要な場合 (特にメソッドの数が多い場合) を除いて、控えめに使用しましょう。
関連
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
画像フィルターアルゴリズムコードのRuby実装
-
Rubyのオブジェクト指向プログラミングでクラスとメソッドの基本を学ぶ
-
Rubyの文法と言語機能のまとめ
-
Rubyのinstance_evalメソッドとclass_evalとの比較
-
RubyおよびRuby on RailsでJSON形式のデータをパースするためのチュートリアルの例
-
RubyのXMLデータパースライブラリ「Nokogiri」の高度な使い方
-
RubyがWeb画像クローリングを実装
-
Rubyのデザインパターン開発におけるProxyパターンの利用について
-
Ruby+Watirの自動テスト環境とWindowsでのデータ読み込みについて
-
Rubyのプライベートとプロテクトを簡単にご紹介します。