Your SlideShare is downloading. ×
0
クラスのインスタンス変数について
クラスのインスタンス変数について
クラスのインスタンス変数について
クラスのインスタンス変数について
クラスのインスタンス変数について
クラスのインスタンス変数について
クラスのインスタンス変数について
クラスのインスタンス変数について
クラスのインスタンス変数について
クラスのインスタンス変数について
クラスのインスタンス変数について
クラスのインスタンス変数について
クラスのインスタンス変数について
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

クラスのインスタンス変数について

5,842

Published on

Ruby勉強会@関西 #48 資料

Ruby勉強会@関西 #48 資料

Published in: Technology, Business
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
5,842
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
10
Comments
0
Likes
1
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. クラスのインスタンス変数について 2011/1/8 cuzic
  • 2. 自己紹介 <ul><li>cuzic といいます </li></ul><ul><ul><li>きゅーじっく と読みます </li></ul></ul><ul><li>Ruby 暦は かれこれもう10年くらい </li></ul><ul><li>Kindle 向けサーバサイドアプリを作成中 </li></ul><ul><ul><li>takibi   <http://www.github.com/cuzic/takibi> </li></ul></ul><ul><ul><ul><li>WEB 上の記事の Scraping ⇒ epub 作成を自動実行 </li></ul></ul></ul><ul><ul><ul><li>4階層モデル( model 、 crawler 、 parser 、 formatter ) </li></ul></ul></ul><ul><ul><ul><li>安価な 共有 WEB ホスティングで動作できるよう工夫 </li></ul></ul></ul><ul><ul><ul><ul><li>デーモンの常駐不要。 Cron で定期的に実行。 </li></ul></ul></ul></ul><ul><ul><ul><li>多数の日本語の WEB 記事に対応 </li></ul></ul></ul><ul><ul><ul><ul><li>JBpress 、 Livedoor Blogos 、日経ビジネスオンライン、 etc </li></ul></ul></ul></ul>
  • 3. Ruby の変数の種類と、インスタンス変数 <ul><li>Ruby の変数には下記の種類がある </li></ul><ul><ul><li>ローカル変数      ・・・ 英小文字から始まる </li></ul></ul><ul><ul><li>インスタンス変数    ・・・ @ から始まる </li></ul></ul><ul><ul><li>クラス変数       ・・・ @@ から始まる </li></ul></ul><ul><ul><li>グローバル変数     ・・・ $ から始まる </li></ul></ul><ul><ul><li>その他 (擬似変数、 定数) </li></ul></ul><ul><li>インスタンス変数とは </li></ul><ul><ul><li>あるオブジェクトに所属する変数 </li></ul></ul><ul><ul><li>同一の 「 @value 」という変数名でも 所属するオブ ジェクトが異なれば、異なるオブジェクトを参照する。 </li></ul></ul>class A    def initialize @value = “” end def get return @value end end a = A.new b = A.new p a.get.object_id p b.get.object_id (参考) クラス変数との違い 同一クラスのインスタンスメソッド、クラスメソッド、クラス定義内 は クラス変数名が同一であれば同一のオブジェクトを参照 している。
  • 4. クラスのインスタンス変数とは <ul><li>Ruby はすべてがオブジェクト </li></ul><ul><ul><li>クラスもオブジェクト ( Class クラスのインスタンス)  ⇒ クラスも通常のオブジェクトと同様、所属する    インスタンス変数を持つことができる </li></ul></ul><ul><li>クラスのインスタンス変数の利用 </li></ul><ul><ul><li>@value の初期化 </li></ul></ul><ul><ul><ul><li>クラス定義内で、クラスのインスタンス 変数を初期化 </li></ul></ul></ul><ul><ul><li>@value2 の初期化 </li></ul></ul><ul><ul><ul><li>クラスメソッド(=クラスの特異メソッド) の中でクラスのインスタンス変数を定義 </li></ul></ul></ul><ul><ul><li>@value 、 @value2 の参照 </li></ul></ul><ul><ul><ul><li>クラスメソッドから参照している </li></ul></ul></ul>class A    @value = Object.new def self.value return @value end    def self.set @value2 = 2 end def self.value2 @value2 end end v = A.value A.set v2 = A.value2
  • 5. クラスのインタンス変数の特徴 <ul><li>サブクラスから参照できない </li></ul><ul><ul><li>クラス B はクラス A とは異なる オブジェクトであるため、 クラス B からクラス A のインスタンス 変数は参照できない。 </li></ul></ul><ul><li>インスタンスメソッドから参照できない </li></ul><ul><ul><li>クラス A と クラス A のインスタンスは 異なるオブジェクト。 </li></ul></ul><ul><ul><li>異なるオブジェクトであるため、 インスタンスメソッドからクラスの インタンス変数にはアクセスできない </li></ul></ul>class A @value = [] def self.value return @value end def instance_method return @value end end class B<A p @value #=> nil end p A.value #=> [] p B.value #=> nil p A.new.instance_method #=> nil (参考) クラス変数との違い クラス変数であれば、サブクラスやインスタンス メソッドから参照できる。
  • 6. クラスのインスタンス変数の長所 class Base def self.civar= val @civar = val end def self.civar @civar end def civar= val self.class.civar = val end def civar self.class.civar end end クラスメソッドを定義することで、 サブクラスで参照可能になる インスタンスメソッドを定義することで、 インスタンスメソッド内で参照可能になる <ul><ul><li>クラスのインスタンス変数は下位クラスから直接参照する ことができないため、参照性を制御しやすい </li></ul></ul>
  • 7. 継承があった場合 class Base def self.civar= val @civar = val end def self.civar @civar end end class Subclass < Base end Base.civar = 1 p Subclass.civar #=> nil Subclass.civar = 2 p Base.civar #=> 1 この行で 1 と表示させたいときは、 後述の class_attribute を利用する ① : Subclass.civar の呼び出し ② : 存在しないので、 Base.civar の呼び出し ③ : インスタンス変数 @civar の  値を返す。このとき self は Subclass のため @civar は未定義 サブクラスはスーパークラスと異なるオブジェクトのため、 同じ名前のインスタンス変数でも異なるオブジェクトを参照する
  • 8. (参考) クラス変数の参照性 <ul><li>Ruby のクラス変数は参照可能な範囲が限定されたグローバル変数 </li></ul><ul><ul><li>変更が全継承階層の同一名のクラス変数に影響する </li></ul></ul>サブクラスから参照可能 インスタンスメソッドから参照可能 サブクラスでの変更がグローバルに影響が及ぶ クラスの インスタンス変数 × (アクセサメソッドが必要) × (アクセサメソッドが必要) × (そもそも参照不可) クラス変数 ○ ○ ○ ActiveSupport の class_attribute (後述) ○ (アクセサメソッド) ○ (アクセサメソッド) (オプションで設定可能) × (破壊的変更を 行った場合を除く) (参考) 定数 ○ ○ × (サブクラスでの定数 への代入文は新定数の定義となる)
  • 9. クラスのインスタンス変数の使用例 <ul><li>Exception2MessageMapper 例外クラスに特定のエラーメッセージ用   フォーマットを関連付けるためのライブラリ </li></ul><ul><ul><li>メッセージフォーマットを Module のインスタンス変数で保持 </li></ul></ul><ul><ul><ul><li>インスタンス変数のため、変数名重複の心配なし </li></ul></ul></ul><ul><ul><ul><li>クラス変数の場合は、変数名重複の場合、誤動作が生じる。 </li></ul></ul></ul>class Foo extend Exception2MessageMapper def_e2message ExsitingExceptionClass, “message …” def_exception :NewExceptionClass, “message …” end Foo.Fail NewExceptionClass, arg … Foo.Fail ExistingExceptionClass, arg …
  • 10. スーパークラスの値をデフォルト値にしたい! <ul><li>ActiveSupport の class_attribute を使うと、 継承時に、デフォルト値としてスーパークラスの値を利用可能 </li></ul>require “rubygems” require “active_support/core_ext/class” class Base class_attribute :setting end class Subclass < Base end Base.setting = true p Subclass.setting #=> true Subclass.setting = false p Subclass.setting #=> false P Base.setting #=> true class Base def self.setting= val class << self self end.class_eval do define_method :setting do val end end end end class_eval
  • 11. class_attribute を利用した例(1) <ul><li>ActiveSupport::Rescuable </li></ul><ul><li>例外処理を rescue_from で体系的に行うためのモジュール </li></ul><ul><li>例外処理のコールバックをクラスのインスタンス変数に格納 </li></ul><ul><ul><li>継承したとき、デフォルトで親のコールバックを利用するように、 前のスライドの class_attribute を利用 </li></ul></ul><ul><li>ActiveSupport::Rescuable のように、クラスに対して新たな機能を付加するモジュールを作成するときは、クラス変数が役立つときがある。 </li></ul>class ApplicationController < ActionController::Base # include ActiveSupport::Rescuable # すでに include している rescue_from ActiveRecord::RecordInvalid do |exception| render :action => (exception.record.new_record? ? :new : :edit) end end
  • 12. class_attribute を利用した例(2) <ul><li>ActiveRecord の場合 </li></ul><ul><ul><li>大量のコールバック が利用可能 </li></ul></ul><ul><ul><ul><li>コールバックは主に クラスのインスタンス 変数に保存 </li></ul></ul></ul><ul><ul><li>コールバックを管理する Observer もクラスの インスタンス変数に保存 </li></ul></ul>クラス内で共通だが、継承ツリー全体での共有はしたくない 設定はクラスのインスタンス変数を用いるとうまく実装できる コールバック タイミング after_create 新規作成し、保存したあと after_destroy 削除したあと after_save 新規作成、更新したあと after_update 更新したあと after_validation バリデーションしたあと before_create 新規作成する前 before_destroy 削除する前 before_save 新規作成、更新する前 before_update 更新する前 before_validation バリデーションする前
  • 13. まとめ <ul><li>Ruby ではクラスもオブジェクト </li></ul><ul><ul><li>クラスもインスタンス変数を持つことができる </li></ul></ul><ul><li>クラスのインスタンス変数は制御しやすい </li></ul><ul><ul><li>アクセサメソッドの定義によって制御可能 </li></ul></ul><ul><ul><li>クラス変数だと、サブクラスからでも変更可能 </li></ul></ul><ul><ul><ul><li>上位クラスも影響を受ける </li></ul></ul></ul><ul><li>Module 内でだけ有効な private なクラス変数として Module 自身のインスタンス変数を使うこともできる </li></ul><ul><li>継承したとき、スーパークラスの値をデフォルト値として使いたいときは、 class_attribute を用いる </li></ul>

×