特異クラス
特異メソッドはどのクラスに所属しているのか。
特異メソッドの定義クラスにおけるインスタンスメソッドだと全インスタンスに引き継がれてしまう。
Objectクラスだと全クラスに引き継がれてしまう。ではどこに所属しているのか。
特異クラスという特殊なクラスに所属している。
特異クラスのオープン
1
2
3
class << an_object
#処理を記述
end
特異クラスの参照を取得
1
2
3
4
5
eigenclass = class << obj
self
end
eigenclass . class # => Class
特異クラスの特別なところ
インスタンスを1つしか持てない(だからシングルトンクラスとも呼ばれる)
継承ができない
特異クラスはオブジェクトの特異メソッドが住んでいる場所
クラスメソッドの構文
この前の記事でクラスメソッドを定義する方法の2つを書いてたけど、もう1つがある。
1
2
3
4
5
6
7
8
class MyClass
class << self
def my_method ; puts "Hello!" end
end
end
MyClass . my_method # => "Hello!"
end
クラスの属性を定義する
1
2
3
4
5
6
7
8
9
class MyClass
# これだとインスタンスの属性定義になってしまう
attr_accessor :a
end
MyClass . a # => NoMethodError: undefined method `a' for MyClass:Class
obj = MyClass . new
obj . a = 1
obj . a # => 1
1
2
3
4
5
6
7
8
class MyClass
class << self
attr_accessor :c
end
end
MyClass . c = 'It works!'
MyClass . c # => "It works!"
クラス拡張
moduleのインスタンスメソッドをクラスメソッドとして定義させるとき
クラス拡張という方法で実現できる。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
module MyModule
def my_method
puts 1
end
end
class MyClass
class << self
# 特異クラス内でインスタンスメソッドを拡張させるとクラスメソッドとして定義可能
include MyModule
end
end
MyClass . my_method # => 1
Object#extendを用いれば、もっとシンプルに定義できる。
1
2
3
4
5
class MyClass
extend MyModule
end
Myclass . my_method # => 1
エイリアス
aliasはキーワードであり、メソッドではいので二つの間にカンマはいらない
参照を向けるのではなく、コピーする。だから、aliasコマンドの後で元となるメソッドに変更が加えられても、aliasによって作成されたメソッドには影響がない
1
2
3
4
5
6
7
8
class MyClass
def my_method ; "my_method()" ; end
alias :my_method2 :my_method
end
m = MyClass . new ()
m . my_method # => "my_method()"
m . my_method2 # => "my_method()"
のように使える。
aliasの用途
元のメソッドを修正したいが、外部ライブラリなどで修正できない場合がある。
その場合は、元メソッドを別名定義し、元メソッド名でメソッドを再定義する。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class MyClass
def my_method
puts "original"
end
alias :my_method2 :my_method
def my_method
puts "changed"
end
end
mc = MyClass . new
mc . my_method # => changed
mc . my_method2 # => original
参照
http://tamata78.hatenablog.com/entry/2015/09/16/205224