目次

Ruby/クラス

Ruby のクラスの概念

Ruby のクラスは Class クラスのインスタンスとして存在する。つまりクラスはオブジェクト。 オブジェクトとしてのクラスにとって Class クラスは klass となる

そしてクラス名は定数ということになる。 つまりスコープに定数がばら撒かれていて、そこにクラスオブジェクトが入っていると思っていい

なので

class Hoge
end

この記法はクラスオブジェクトリテラル+定数設定ということになる。

基本的なクラスの作り方

class キーワードに続きそのクラスの名前をつけて end で閉じればよい。メソッドは def キーワードに続きブロックを作ればいい

class Hoge
  def hoge
    print "ほげ"
  end
 
  def piyo
    print "ぴよ"
  end
end
class クラス名
  def メソッド名
    #処理内容
  end
end

クラス名の命名規約

Rubyのクラス名の命名規約はJavaと同じでパスカル方式

HogePiyo

ファイル名の命名規約

全部小文字のハイフン繋ぎ。Rubyは複数のクラスを1個のファイルに記述できるが、そのなかでもインターフェースとなる主要なクラスをファイル名の元ネタとして使うのが一般的

hoge-piyo.rb

クラスを継承する

このように継承したいクラスを(例ならPiyo)リダイレクトで突っ込むように書く

class Hoge < Piyo
  def hoge
    print "ほげ"
  end
end

クラスメソッド(静的メソッド、スタティックメソッド)

クラスメソッドは self かクラス名をメソッドの頭につけることによって作れる。 通常はクラス名変更のリファクタを考慮するから self を使う

class Hoge
  def Hoge.hoge
    print "ほげ"
  end
 
  def self.piyo
    print "ぴよ"
  end
end

つまり self はそのオブジェクト内ではオブジェクト自身を指すことになる。 なんでそうなるかといえば、Ruby にとって class は Classクラスのインスタンスになる。class Hoge~の記述は class 宣言ではなく、class インスタンスリテラルと捉えられる。

なので class ~ end 中の self は Class クラスのインスタンス自身を指すことになり、クラスメソッドに self をつけるのはそういう意味なのだ。

なのでそのクラスメソッド内部のselfもクラス自身を表すことになる

class Hoge
  def self.piyo
    print "ぴよ"
  end
 
  def self.fuga
    print self.piyo
    print "ふが"
  end
end
 
Hoge.fuga //=>"ぴよふが"

逆にインスタンスのメソッドを呼び出すときは内部のselfはオブジェクト=インスタンス自身となる。

コンストラクタ

コンストラクタは特別なメソッド initialize で定義する。

class Hoge
  def initialize(a)
  end
end

Rubyには型が無いのでJavaのような引数の数と型による多態性は内部で自分で実装すれば実現できる。

メソッドを動的に追加する

インスタンスメソッド

RubyはJavaとかと違ってコード動作中で動的にクラスにメソッドを追加できる

class Hoge
  def hoge
    print "ほげ"
  end
end
 
if(true)
  class Hoge
    def piyo
      print "ぴよ"
    end
  end
end
 
aaa = Hoge.new()
aaa.piyo()    #=> "ぴよ"

こんな風に既に定義されているクラスでもう一度定義すると再定義ではなくて追加になる

オブジェクトの作られたタイミングと追加したメソッドの実行には関係が無い。だからこれもOK。

class Hoge
  def hoge
    print "ほげ"
  end
end
aaa = Hoge.new()
 
if(true)
  class Hoge
    def piyo
      print "ぴよ"
    end
  end
end
 
aaa.piyo()    #=> "ぴよ"

つまりメソッドは実行時にklassポインタをたどって検索されるという話

クラスメソッド

クラスメソッドを後付で追加するにはクラスオブジェクト自体の特異メソッドとして追加すれば実現できる。

class Hoge
end
 
class <<Hoge
  def hello
    puts "hello"
  end
end
 
Hoge.hello

メソッドを動的に特定のオブジェクトのみに追加する(特異メソッド)

Javascriptのように特定のオブジェクトのみにメソッドを追加できる

class Hoge
  def hoge
    print "ほげ"
  end
end
aaa = Hoge.new()
 
#ここで追加
def aaa.piyo
  print "ぴよ"
end
 
aaa.piyo()    #=> "ぴよ"
 
bbb = Hoge.new()
bbb.piyo()   #=>エラー

特定オブジェクトのみにMixinする

特異メソッド的な機能をmoduleを使ってやることもできる。これにはextendメソッドを使う

#モジュール
module Piyo
  def piyo
    print "ぴよ"
  end
end
 
#クラス
class Hoge
  def hoge
    print "ほげ"
  end
end
 
a = Hoge.new()
 
#ここでmix-in
a.extend Piyo
a.piyo()    #=>"ぴよ"
 
b = Hoge.new()
b.piyo()    #=>エラー

メソッドのオーバーロード

Ruby では Java のような同一メソッド名の引数によるシグネチャ違いをたくさん定義することができない。 その代わりにオプション引数とか rest 引数というものを駆使してやると同じようなことができる

つまりメソッドの引数は一番細かい粒度で作っておき、プリセットの値をオプションで埋めておくことで対応。

class Hoge
  def hoge(a, b=1, c=2)
    #何か処理
  end
end

メソッドの再定義

インスタンスメソッド

同名のメソッドでメソッド追加してやるとメソッドの再定義になる

class Hoge
  def hello1
    puts "hello1"
  end
end
 
class Hoge
  def hello1
    puts "hello1+"
  end
end
 
Hoge.new.hello1 #=>"hello1+"

再定義したいんだけど、前の定義も利用したい場合は、このように既存のメソッドに別名をつけておいてポインタを掴んでおく。 そうした上で既存の名前を上書きする。

class Hoge
  def hello1
    puts "hello1"
  end
end
 
class Hoge
  def hello1_plus
    hello1_inner   #既存のメソッドを別名を利用して実行
    puts "+"
  end
  alias_method :hello1_inner, :hello1
  alias_method :hello1, :hello1_plus  #既存のメソッドを上書き
end
 
Hoge.new.hello1

つまりこれは実行タイミングと定義タイミング、上書きタイミングをずらすためにaliasを使っている。

クラスメソッド

こちらもインスタンスメソッドと同様に同名でもう一度定義させれば再定義になる。

class Hoge
  def self.hello1
    puts "hello1"
  end
end
 
class Hoge
  def self.hello1
    puts "hello1+"
  end
end
 
Hoge.hello1 #=> "hello1+"

既存のクラスメソッド利用したい場合は特異メソッドの記法を用いて内部に「オブジェクト空間」のようなものを作ってそれに対して操作をかける事によって文法的に整合性をとりつつ、 既存のものを利用しつつ上書きできる。

class Hoge
  def self.hello1
    puts "hello1"
  end
end
 
class Hoge
  class <<self
    def hello1_plus
      hello1_inner
      puts "+"
    end
    alias_method :hello1_inner, :hello1
    alias_method :hello1, :hello1_plus
  end
end
 
Hoge.hello1

このことから特異メソッドの「«」の記法は他の言語で言う「with」のような効果があることがわかる。

Mixin(メソッドだけ単独で借りてくる)

Ruby はメソッドの実装だけ単独で借りてくることができる Mixin という機能がある

オブジェクト自身(JavaとかC++でのthis)

Ruby では self キーワードであらわす

演算子の定義

Rubyでは演算子自体もメソッド呼び出しとして実装されている。 だがこいつのうまい使い方がいまいちわからんwww

二項演算子

class Hoge
  def +(a)
    print a
  end
end
 
a = Hoge.new()
a + "がおー"

単項演算子

class Hoge
  attr_accessor :aaa
  def +@
    print self.aaa
  end
end
 
a = Hoge.new()
a.aaa = "がおー"
+a

クラス定数

クラス定数を作る

クラス定数は慣例的にスネークケースのアッパーで書く。class記述の直下にバンと書けばOK

class Hoge
  PIYO = "1"
end

クラス定数へのアクセス

外部からのアクセス コロン2個のスコープ解決を使って書く

PIYO = "2"
class Hoge
  PIYO = "1"
end
p Hoge::PIYO #=>"1"

クラスメソッドからのアクセスは何もつけずにOK・・・何かつけちゃだめ

PIYO = "2"
class Hoge
  PIYO = "1"
  def self.piyo
    p PIYO
  end
end
Hoge.piyo #=>"1"

インスタンスメソッドは同じく何もつけずにOK・・・何かつけちゃだめ

PIYO = "2"
class Hoge
  PIYO = "1"
  def piyo
    p PIYO
  end
end
Hoge.new.piyo #=>"1"

参考サイト

Tag