2018-01-03 | 技術開発

自由なRubyのクラス(一)

Thumb diamond 704072 960 720

昔、学生だったころ、よく「自由」とは何であるかを考え、将来は自由な生活が送れるだろうと思っていた。だが実際に社会に出てみると、依然として自由自在ではいられない多くの制約があった!

しかしRubyの世界におけるクラスは非常に自由である。

Rubyに少しでも触れたことのある者はいくつかの特徴を知っているにちがいない。
● Rubyがオブジェクト指向言語であること
● すべてがオブジェクトであること。

Class

RubyではすべてのクラスがClass(クラス)のクラスである。

Object.class
# => Class

Kernel.class
# => Module
Module.class
# => Class

Moduleも一つのクラスとみなされる。つまり、すべてがClassというクラスに分類される。

Class.classはClass そのものを示している。

Anonymous Class

クラスがどのようにして生みだされたのか? 名前のついていないクラスからそれを知ることができる。
Class.new => #<Class:0x007f85fc30ea88>
これで新しいクラス(オブジェクト)が得られたので実際に動かすことができる。

klass = Class.new
klass.new => <#<Class:0x007f85fc30ea88>:0x007f85fc2efa98>

このクラスは哀れでまだ名前を付けられてないので、オブジェクト本体の<Class:0x007f85fc30ea88>のままである。
では、どのようにこれらに名前をつけたらいいか。

Klass = Class.new
Klass.new => #<Klass:0x007f85fc2d7510>

実際にはすべてのクラスの名前は一つの定数であるから、クラスに名前を付けるときには大文字で始めなければならない(大文字で書くことによってはじめてクラスが定数として定義される)。
しかし、メソッドによるクラスの継承はどうすればいいだろうか。

Klass = Class.new(Object) do
  def echo(text)
    puts text
  end
end

実際には、初期化のときにクラスの中にブロックを入れ、それを働かせるようにする。
上述したクラスの定義は下の定式codeと等しい。

class Klass
  def echo(text)
    puts text
  end
end

それでclassからendまでで示されているのが一つのブロックの可能性があることが分かる。

Class Methods

この段落で論じるのはクラスメソッドについてで、クラスメソッドもクラス化できるということが興味深い。
オブジェクト指向には二つのメソッドがある。
● クラスメソッド      Klass.instance
● インスタンスメソッド  Klass.new.echo
クラスメソッドとインスタンスメソッドの違いは、インスタンスメソッドのほうはクラスを.newで初期化してからはじめて、これらのメソッドにアクセスできるということである。
まずはどのようなクラスメソッドが使えるか見てみよう。

Class.methods
# => [:include, ...,:instance_exec, :__id__]

いくつかのメソッドを省略したが、includeというなじみのキーワードが見えてきた。

class Klass
  include Mod
end

まさしく我々が見たincludeはあるモジュールの中のincludeである。
それゆえ下の動作は、実際は等しいものなのである。

Klass = Class.new do
  include Mod
end

class Klass
  include Mod
end

Klass.include Mod

上記の探索を通してほとんどのRubyistがRails中に、多くのこのような応用方式があることを発見するのではなかろうか。

class User < ApplicationRecord
  has_many :posts
end

上の例から見て、has_manyはクラスメソッドであり、ApplicationRecordまたはその上のオブジェクトに属している可能性がある。

まとめ

Rubyの世界では、すべてのクラスが実際にはClassで表されるものであり、クラスメソッドは元のクラスをベースにして新しいクラスを作るときのブロックとして使用することができ、クラスの多様性を開発するのに用いることができる。
次の文章でhas_manyの実際の応用について説明する。

Categories

Archives