Ruby お勉強の自分用メモ
インスタンスごとに異なる値を持つ変数
@
から始まる変数名で定義する
インスタンス変数はデフォルトでは外部からアクセスすることはできない、
アクセス可能にするにはアクセサの属性を設定する必要がある
class Todo
def initialize(task, limit)
@task = task
@limit = limit
end
def display
"#{@task}: limit: #{@limit}"
end
end
todo01 = Todo.new('Taks01', '2019-11-10')
todo02 = Todo.new('Taks02', '2019-11-20')
puts todo01.display
puts todo02.display
todo01.@task
todo01.task
class Todo
attr_accessor :task
end
p todo01.task
アクセサ属性
キーワードにインスタンス変数名をシンボルの形式で渡すことで設定
attr_accessor
... getter , setter を設定
attr_reader
... getter のみを設定
attr_writer
... setter のみを設定
class Idol
attr_reader :name
attr_writer :type
attr_accessor :rank
def initialize(name, type, rank = 100)
@name = name
@type = type
@rank = rank
end
def display
puts "#{@name} (#{@type}) Rank: #{@rank}"
end
end
aoi = Idol.new('Kiriya Aoi', 'cool')
aoi.display
p aoi.rank
aoi.rank = 3
p aoi.rank
p aoi.name
aoi.name = 'Hoshimiya Ichigo'
p aoi.type
aoi.type = 'pop'
aoi.display
attr_accessor
の設定は下記の様に独自にgetter, setter を設定するのと同等
class Foo
def initialize(name = 'foo')
@name = name
end
def name
@name
end
def name=(val)
@name = val
end
end
foo = Foo.new
p foo.name
foo.name = 'bar'
p foo.name
インスタンス変数は値がセットされて始めて生成される
class Idol
attr_accessor :name
def my_name_is(name)
@name = name
end
end
hoshimiya = Idol.new
p hoshimiya.instance_variables
p hoshimiya.name
hoshimiya.my_name_is 'Ichigo'
p hoshimiya.instance_variables
p hoshimiya.name
アクセサの状態とインスタンス変数のアクセス可能な方法の違い
getter, setter の有無によってインスタンス変数にアクセス可能な表記とアクセスできない表記がある
class Hoo
attr_accessor :read_get_var
attr_reader :read_only_var
attr_writer :write_only_var
def initialize
@read_get_var = "has_accessor"
@read_only_var = "has_rader"
@write_only_var = "has_writer"
@no_accessor = "no_accessor"
end
def call_by_at
p @read_get_var
p @read_only_var
p @write_only_var
p @no_accessor
end
def call_by_self
p self.read_get_var
p self.read_only_var
p self.write_only_var
p self.no_accessor
end
def call_by_no_recever
p read_get_var
p read_only_var
p write_only_var
p no_accessor
end
end
hoo = Hoo.new
hoo.call_by_at
hoo.call_by_self
hoo.call_by_no_recever
メソッド内で @
無しの変数名でのアクセスは、self
の省略形になるので、self.変数名
と同じ結果になる
インスタンス変数はクラスからはアクセスできない
インスタンス変数は、アクセサを設定してもクラスからはアクセスできない
class Bar
attr_accessor :my_name
def initialize
@my_name = 'bar'
end
end
bar = Bar.new
p bar.my_name
Bar.my_name
クラスメソッドのを作成してもインスタンス変数はインスタンスごとに異なる値を持つのでアクセスできない
class Bar
attr_accessor :my_name
def initialize
@my_name = 'bar'
end
def self.my_name
@my_name
end
end
p Bar.my_name
クラス変数
@@
で始まる変数名で定義する
クラス変数は、クラスと子孫クラス・それらのクラスのインスタンス変数で共有される
クラス変数にはアクセサ属性が適応できないので、getter, setter は独自に設定する必要がある
class Foo
@@class_name = 'foo'
def display
puts "#{self.class} class_name is #{@@class_name}"
end
end
class Bar < Foo
def class_name
@@class_name
end
def class_name=(val)
@@class_name = val
end
end
class Baz < Foo
def self.class_name
@@class_name
end
def self.class_name=(val)
@@class_name = val
end
end
foo = Foo.new
bar = Bar.new
baz = Baz.new
foo.display
bar.display
baz.display
bar.class_name = 'bar'
p bar.class_name
foo.display
bar.display
baz.display
p Baz.class_name
Baz.class_name = "xxx"
p Baz.class_name
p bar.class_name
foo.display
bar.display
baz.display
Foo.class_name
foo.class_name
クラス変数はインスタンスメソッド内でも定義できるが、メソッドを通って値が渡されるまでクラス変数は設定されない
class Hoo
def initialize
@@class_name = 'hoo!'
end
def self.class_name
@@class_name
end
end
p Hoo.class_name
p Hoo.class_variables
hoo = Hoo.new
Hoo.class_name
Hoo.class_variables
継承させた子孫クラスでも同様
class Xoo < Hoo
@@xoo_var = 'xoo'
def self.xoo_var
@@xoo_var
end
end
Xoo.class_name
xoo = Xoo.new
p Hoo.class_name
p Hoo.class_variables
p Xoo.class_name
Xoo.xoo_var
Hoo.xoo_var
クラスインスタンス変数は変数が設定されたクラスからのみ参照できる変数で、クラスのインスタンスや子孫クラスからは参照できない
変数名は @
から始めクラス定義はclass式内のトップレベルまたはクラスメソッド内に定義する (※ 通常のメソッド内で定義するとインスタンス変数になる)
クラスインスタンス変数は、クラス変数と同様でアクセサは自前で実装する必要がある
class CuteIdol
@type = 'cute'
def initialize(name)
@name = name
end
def say_my_type
p @type
end
def display
puts "#{@name} type is #{CuteIdol.type}!"
end
def self.display
puts "#{self} Class type is #{@type}"
end
end
CuteIdol.display
p CuteIdol.instance_variables
ichigo = CuteIdol.new('Hoshimiya Ichigo')
ichigo.say_my_type
ichigo.display
class CuteIdol
def self.type
@type
end
def self.type=(val)
@type = val
end
end
ichigo.display
クラスメソッド内で定義
class Xoo
def self.init
@xoo = 'xoo'
end
def self.xoo
@xoo
end
def xoo
@xoo
end
end
xoo = Xoo.new
Xoo.init
p Xoo.xoo
p xoo.xoo
class Zoo < Xoo
end
p Zoo.xoo
クラスインスタンス変数は子孫クラスからもアクセスできない
class Foo
@class_name = 'foo'
def self.display
puts "#{self} name is #{@class_name}"
end
def self.class_name
@class_name
end
end
class Hoo < Foo
def self.hi
p @class_name
end
end
Foo.display
p Foo.class_name
p Foo.instance_variables
Hoo.display
Hoo.hi
p Hoo.class_name
p Hoo.instance_variables
クラス定数
class式内のトップレベルに大文字から始まる変数を定義するとクラス定数になる
クラス定数は子孫クラスからもアクセス可能
定数なので変更しようとすると warning が発生する
class StarLightStudent
SCHOOL_NAME = 'StarLight'
attr_reader :name
def initialize(name)
@name = name
end
def display
puts "#{@name} - #{SCHOOL_NAME} Scholl"
end
end
class Idol < StarLightStudent
def initialize(name, type)
super name
@type = type
end
def display
puts "#{@name} (#{@type}) - #{SCHOOL_NAME} Scholl"
end
end
p StarLightStudent::SCHOOL_NAME
akari = StarLightStudent.new('Ozora Akari')
akari.display
ichigo = Idol.new('Hoshimiya Ichigo', 'cute')
ichigo.display
クラス定数に外部からアクセスするには getter を独自に作成する必要がある
setter を定義すると warning が発生する
class Week
DAY_OF_WEEK = 7
def self.DAY_OF_WEEK
DAY_OF_WEEK
end
def self.DAY_OF_WEEK=(val)
DAY_OF_WEEK = val
end
end
p Week.DAY_OF_WEEK
Week::DAY_OF_WEEK = 3
p Week.DAY_OF_WEEK
トップレベルに定義された定数は Object
のクラス定数として定義される
HOGE = 'hoge!'
p Object::HOGE
class Hoge
HOGE = 'fugafuga'
def say
p HOGE
p Object::HOGE
end
end
Hoge.new.say
クラスの定義は、クラスを表す Class クラスのインスタンスを作成し、そのインスタンスを参照するクラス名の定数を作成するので、クラス名と定数名が被っているとエラーになる
HOGE = 'hoge!'
class HOGE
end
まとめ
- インスタンス変数はクラス内のメソッドで使う時は
@変数名
にしておけば間違いなさそう
- クラス内に作れる変数は、外部からアクセスするには基本的にアクセサが必要
インスタンス変数は attr_
でアクセサを作成することができるが、それ以外は独自に必要なメソッドを作成する必要がある
- インスタンス変数は
@
で始まる変数名でメソッド内に定義
変数定義は子孫クラスにも引き継がれインスタンスごとに異なる値を持つのでインスタンスからのみアクセス可能
インスタンス変数は、値がセットされて始めて生成される
- クラス変数は
@@
で始まる変数名で定義・クラス定数は 大文字から始まる変数名で定義
クラス変数・クラス定数は、クラスと子孫クラス、それらのインスタンスから参照できる
- クラスインスタンス変数は
@
で始まる変数名で class式内のトップレベルまたは、クラスメソッド内に定義
クラスインスタンス変数は、変数の定義されたクラスからのみ参照可能
- クラス定義はトップレベルに定数として定義される