SlideShare a Scribd company logo
1 of 37
Download to read offline
Rubyの
インスタンス変数
class Sample
@hanako = "aa"
!
def hanako
@hanako
end
end
# インスタンス変数を外から参照する
object.instance_variable_get(:@val)
!
# インスタンス変数を外から設定する
object.instance_variable_set(:@val, “value”)
!
# インスタンス変数の一覧を配列で取得する
object.instance_variables
!
# includeされた時のフック
included(klass)
!
# 継承された時のフック
inherited(klass)
!
# 定義されているか調べる
defined?(@hanako)
今回使う変わり種メソッド
Hands on
JavaからRubyにきたときに
最初にふに落ちなかったのがこれ
class Sample
@hanako = "shibainu"
!
def hanako
@hanako
end
end
!
Sample.new.hanako # => nil
shibainu じゃないの?!
インスタンス変数の定義
[ オブジェクトの状態を表す ]
オブジェクト オブジェクト
インスタンス変数は
各オブジェクト毎に所属し
オブジェクト
インスタンス変数を値をセットするのは
箱の一つにラベルを付けて値を
保存するようなイメージ
aa @hanako
class Sample
@hanako = "aa"
!
def hanako
@hanako
end
end
!
Sample.new.hanako # => nil
クラスとして実行される
インスタンスとして実行される
インスタンス変数はアクセスされた時の
カレントオブジェクト(self)に所属する
所属先が
違うので
違う変数
Hands on
instance_variable_get
を使ってSampleクラスの
@hanakoインスタンス変数
を表示してください
class Sample
@hanako = "aa"
!
def hanako
@hanako
end
end
!
puts ????? #=> “aa”
Hands on
class Sample
@hanako = "aa"
!
def hanako
@hanako
end
end
!
puts Sample.instance_variable_get(:@hanako) # => "aa"
Answer
正しい初期化
class Sample
def initialize
@hanako = "aa"
end
!
def hanako
@hanako
end
end
!
Sample.new.hanako # => "aa"
カレントオブジェクトは?
class Sample
def initialize
@hanako = "aa"
end
!
def hanako
@hanako
end
end
!
Sample.new.hanako # => "aa"
クラス
インスタンス
インスタンス
所属先が
同じなので
同じ変数
インスタンス変数は
selfで取得できる
カレントオブジェクトに所属する
Hands on
@hanakoを返す
Getterを作って
出力してください
class Sample
@hanako = “aa”
!
????
end
!
puts ???? #=> "aa"
Hands on
class Sample
@hanako = "aa"
!
def self.hanako
@hanako
end
end
!
puts Sample.hanako # => aa
Answer
class Sample
@hanako = "aa"
!
def self.hanako
@hanako
end
end
!
puts Sample.hanako # => aa
class定義内のselfはクラス自身
特異メソッド内のselfもクラス自身
クラス
Hands on
includeすると
hanakoアクセッサが
追加されるmoduleを作って
ください
module HanakoAttribute
????
end
!
class Shibainu
include HanakoAttribute
end
!
ins = Shibainu.new
ins.hanako = "tarou"
puts ins.hanako #=> "tarou"
Hands on
module HanakoAttribute
def hanako
@hanako
end
!
def hanako=(val)
@hanako = val
end
end
!
class Shibainu
include HanakoAttribute
end
!
ins = Shibainu.new
ins.hanako = "tarou"
puts ins.hanako # => tarou
Answer
Hands on
module HanakoAttribute
def hanako
@hanako
end
!
def hanako=(val)
@hanako = val
end
end
!
class Shibainu
include HanakoAttribute
end
!
ins = Shibainu.new
ins.hanako = "tarou"
puts ins.hanako # => tarou
Answer
Hands onModuleをクラスに????して
アクセッサを追加して下さい
module HanakoAttribute
def hanako
@hanako
end
!
def hanako=(val)
@hanako = val
end
end
!
class Shibainu
???? HanakoAttribute
end
!
Shibainu.hanako = "tarou"
puts Shibainu.hanako # => tarou
Hands on
module HanakoAttribute
def hanako
@hanako
end
!
def hanako=(val)
@hanako = val
end
end
!
class Shibainu
extend HanakoAttribute
end
!
Shibainu.hanako = "tarou"
puts Shibainu.hanako #=> tarou
Answer
Hands on
module HanakoAttribute
def hanako
@hanako
end
!
def hanako=(val)
@hanako = val
end
end
!
class Shibainu
extend HanakoAttribute
end
!
Shibainu.hanako = "tarou"
puts Shibainu.hanako #=> tarou
Answer
includeでクラスメソッドも
一緒に足すイディオム
module HanakoAttribute
# define instance methods
!
def self.included(klass)
klass.extend ClassMethods
end
!
module ClassMethods
# define class methods
end
end
!
def Sample
include HanakoAttribute
end
★ インスタンスとクラス両方に

同じアクセッサが存在する
★ クラスアクセッサで設定

された値がインスタンスの

アクセッサの初期値となる
★ インスタンスのセッターで

インスタンスの値は変更できる

がクラスの値には影響がない
module HanakoAttribute
# define instance methods
!
def self.included(klass)
klass.extend ClassMethods
end
!
module ClassMethods
# define class methods
end
end
!
class Sample
include HanakoAttribute
end
!
Sample.tarou = "a"
ins = Sample.new
ins.tarou #=> "a"
!
ins.tarou = "b"
ins.tarou #=> "b"
Sample.tarou #=> "a"
Hands on
Hands on
module HanakoAttribute
def self.included(klass)
klass.extend ClassMethods
end
!
def tarou
if defined?(@tarou)
@tarou
else
self.class.instance_variable_get(:@tarou)
end
end
!
def tarou=(val)
@tarou = val
end
!
module ClassMethods
def tarou
@tarou
end
!
def tarou=(val)
@tarou = val
end
end
end
!
class Sample
include HanakoAttribute
end
Answer
Hands on
module HanakoAttribute
def self.included(klass)
klass.extend ClassMethods
end
!
def tarou
if defined?(@tarou)
@tarou
else
self.class.instance_variable_get(:@tarou)
end
end
!
def tarou=(val)
@tarou = val
end
!
module ClassMethods
def tarou
@tarou
end
!
def tarou=(val)
@tarou = val
end
end
end
!
class Sample
include HanakoAttribute
end
Answer
Hands on
module Attribute
def self.included(klass)
klass.extend ClassMethods
end
!
def to_hash
????
end
!
module ClassMethods
def attribute(name)
????
end
end
end
!
class Model
include Attribute
!
attribute :hanako
attribute :tarou
end
!
ins = Model.new
ins.hanako = "shiba"
ins.tarou = "chiwarani"
ins.to_hash
#=> {hanako: "shiba", tarou: "chiwarani"}
★ アクセッサを定義できる

クラスメソッドを定義

してください
★ 設定された値をhashで

返すto_hashメソッドを

定義してください
Hands on
module Attribute
def self.included(klass)
klass.extend ClassMethods
end
!
def to_hash
Hash[
self.class.instance_variable_get(
:@attribute_names).map do |n|
!
[n, __send__(n)]
end
]
end
!
module ClassMethods
def attribute(name)
(@attribute_names ||= []) << name
attr_accessor name
end
end
end
!
class Model
include Attribute
!
attribute :hanako
attribute :tarou
end
Answer
Hands on
module Attribute
def self.included(klass)
klass.extend ClassMethods
end
!
def to_hash
Hash[
self.class.instance_variable_get(
:@attribute_names).map do |n|
!
[n, __send__(n)]
end
]
end
!
module ClassMethods
def attribute(name)
(@attribute_names ||= []) << name
attr_accessor name
end
end
end
!
class Model
include Attribute
!
attribute :hanako
attribute :tarou
end
Answer
Hands on
class Sub < Model
end
!
ins = Sub.new
ins.tarou = "hanako"
ins.to_hash
先ほど作ったModelを
継承してみてください
Hands on
class Sub < Model
end
!
ins = Sub.new
ins.tarou = "hanako"
ins.to_hash
# => undefined method `map' for nil:NilClass (NoMethodError)
エラー?!
インスタンス変数は代入があったときに
初めて作られる
class Sample
class << self
attr_accessor :hanako
end
end
!
Sample.instance_variables # => []
Sample.hanako = "a"
Sample.instance_variables # => [:@hanako]
インスタンス変数に継承は関係ない
class Sample
class << self
attr_accessor :hanako
end
end
!
Sample.instance_variables # => []
Sample.hanako = "a"
Sample.instance_variables # => [:@hanako]
!
!
class Sub < Sample
end
!
Sub.instance_variables # => []
Sub.hanako = "a"
Sub.instance_variables # => [:@hanako]
引き継が
れてない
Hands on
module Attribute
def self.included(klass)
klass.extend ClassMethods
end
!
def to_hash
Hash[
self.class.instance_variable_get(
:@attribute_names).map do |n|
!
[n, __send__(n)]
end
]
end
!
module ClassMethods
def attribute(name)
(@attribute_names ||= []) << name
attr_accessor name
end
end
end
!
class Model
include Attribute
!
attribute :hanako
attribute :tarou
end
inheritedを使って
Attributeの定義を
引き継ぐように
して下さい
最
終
問
題
Hands on
module Attribute
def self.included(klass)
klass.extend ClassMethods
end
!
def to_hash
Hash[
self.class.instance_variable_get(
:@attribute_names).map do |n|
!
[n, __send__(n)]
end
]
end
!
module ClassMethods
def inherited(sub)
sub.instance_variable_set(
:@attribute_names, @attribute_names.dup)
end
!
def attribute(name)
(@attribute_names ||= []) << name
attr_accessor name
end
end
end
Answer
最
終
問
題
Hands on
module Attribute
def self.included(klass)
klass.extend ClassMethods
end
!
def to_hash
Hash[
self.class.instance_variable_get(
:@attribute_names).map do |n|
!
[n, __send__(n)]
end
]
end
!
module ClassMethods
def inherited(sub)
sub.instance_variable_set(
:@attribute_names, @attribute_names.dup)
end
!
def attribute(name)
(@attribute_names ||= []) << name
attr_accessor name
end
end
end
Answer
最
終
問
題
class Sample
class_attribute :hanako
end
補
足
あっ、Railsならclass_attribute
使うのが楽です( ˘ω˘)
ご清聴ありがとうございました

Rubyインスタンス変数