0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

読書ログ『メタプログラミング Ruby 第2版』2章

Last updated at Posted at 2020-02-24

2章 月曜日: オブジェクトモデル

オブジェクトモデル

全ての 言語要素(クラス、モジュール、インスタンス変数 etc...)が共存しているシステムのこと。

以下の2つの質問に答える場所

  • このメソッドはどのクラスに所属するものなのか
  • このモジュールをincludeしたら何が起きるのか

2.1 オープンクラス

オープンクラス

  • いつでも既存のクラスを再オープンして、そのばで修正できる技法のこと
    • (既存クラスには、String,Arrayなど標準クラスも含む)

classキーワード

  • クラス宣言。主な仕事はクラスのコンテキストに連れて行くこと。

  • Rubyではクラスを定義するコードと、その他のコードに違いはない。

モンキーパッチ

  • オープンクラスを否定的に言う、蔑称。

  • 何も考えずにクラスにコードを追加することで、既存のメソッドを上書きし、意図しない挙動を生み出すこと。

  • Refinementsを使うことで、安全にモンキーパッチを利用できるようになる。

2.2 オブジェクトモデルの内部

インスタンス変数

  • オブジェクトに存在する

  • 値が代入されたときに初めて出現する

    • Rubyのオブジェクトのクラスと、インスタンス変数には何のつながりもない!
  • メソッドを呼び出さなければ、インスタンス変数は存在しない。

class MyClass
	def my_method
		@v = 1
	end
end

obj = MyClass.new
obj.instance_variables => []
obj.my_method => 1
obj.instance_variables => [:@v]

メソッド

  • メソッドはオブジェクトではなく、クラスに存在する
    • オブジェクトにはメソッドはなく、インスタンス変数とクラスへの参照があるだけ

クラスとは

  • クラスはClassクラスのオブジェクト
    • オブジェクトのメソッド → そのクラスのインスタンスメソッド
    • クラスのメソッド → Classクラスのインスタンスメソッド
  • 全てのクラスは、モジュールである
    • クラスとは、インスタンスの生成と継承のための3つのメソッドをもつモジュール
  • クラス名は、定数

定数

  • 大文字で始まる参照は、クラス名やモジュール名を含めて、全て定数
  • プログラムにある全ての定数は、ファイルシステムのようにツリー状に配置
    • モジュール: ディレクトリ / 定数: ファイル
  • 定数ツリーの奥にいるときは、ルートを示すコロン2つで書き始めれば、外部の定数を絶対パスで指定できる
Y = 'ルートレベルの定数'

module M
	Y = 'Mにある定数'
	Y #=> "Mにある定数"
	::Y #=> "ルートレベルの定数"
end

オブジェクトとクラスのまとめ

オブジェクト

  • インスタンス変数の集まりにクラスへのリンクがついたもの

インスタンスメソッド

  • オブジェクトではなく、オブジェクトのクラスに住む

クラス

  • オブジェクトにインスタンスメソッドの一覧とスーパークラスのリンクがついたもの

クラス名

クラスへのアクセスを行うための参照

2.4 メソッドを呼び出すときに何が起きているの?

  1. メソッドを探す。メソッド探索
  2. メソッドを実行する。selfが必要

メソッド探索

  • Rubyがレシーバのクラスに入り、メソッドを見つけるまで、継承チェーンを上ること。

「右へ一歩、それから上へ」

  • レシーバのクラスに向かって右へ一歩進み、メソッドが見つかるまで継承チェーンを上へ進む。

レシーバ

  • 呼び出すメソッドが属するオブジェクト

継承チェーン

  • スーパークラスを、BasicObjectまで続けたとき、通ったクラスの道筋のこと

モジュールとメソッド探索

  • モジュールをクラスにインクルードすると、Rubyはモジュールを継承チェーンに挿入する
    • include: インクルードしたクラスの上にモジュールが挿入される
    • Prepende: 下にモジュールが挿入される

Kernal

  • Objectクラスが、Kernelモジュールをincludeしているので、全てのオブジェクトの継承チェーンに、Kernelモジュールが挿入される

メソッドの実行

selfキーワード

  • メソッドを呼び出すとき、メソッドのレシーバがselfになる
    • レシーバを明示しないメソッド呼び出しは、全てselfに対する呼び出しになる。
    • 他のオブジェクトを明示してメソッドを呼び出すと、今度はそのオブジェクトがselfになる
  • 最後にメソッドのレシーバとなったオブジェクトが、selfとなる

トップレベル

  • メソッドを呼び出さないときselfになるのは、Objectクラスのインスタンスのmain
self #=> main
self.class #=> Object

クラス定義とself

  • クラスやモジュールの定義の内側(メソッドの外側)では、selfの役割はクラスやモジュールそのもの
class MyClass
	self #=> MyClass
end

Refinements

  • Refinementsが有効になる場所
    • refineブロック
    • usingを呼び出した場所からモジュールの終わりまで(モジュール定義にいる場所 / ファイルの終わりまで(トップレベルにいる場合)
  • クラスをリファインすると言うのは、元のコードにパッチを貼り付けるようなもの
    • リファインされた側のクラスよりも優先される
    • インクルードやプリペンドしたものより優先される

感想

これまで、オブジェクトがメソッド・変数を持つと、漠然とまとめて理解していたので、インスタンス変数は、オブジェクトに存在する / メソッドはオブジェクトではなく、クラスに存在すると整理できたのがかなり、すっきりきたーーーー(ような気がする。)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?