Class (vol.1 クラスとは)

Ruby でのプログラミングは、オブジェクトたちが飛び回り、踊り歌う世界の台本を書く作業と言えるかもしれません。
新しいクラスを作ることは、キャラクターの新しい種族を作れるようになることに相当します。
新しいクラスを作ることで、新しい特徴を持ったキャラクター(プログラミングの世界ではオブジェクト)を作ることができます。

  • オブジェクトは、自分が所属するクラスが持つメソッドを使うことができる
    • OK : 1.even?
    • NG : "1".even?
  • new メソッド → そのクラスのオブジェクト(インスタンス)を作る
    • Hoge.newHoge クラスのインスタンスを作る

クラスに新しくメソッドを定義することは、ゲームキャラクターが新しい呪文を覚えることに相当します。
キャラクターが呪文を覚えるとできることが増えるように、オブジェクトもメソッドを呼び出せるようになると、できることが増えていきます。

クラスとは

  • 各種オブジェクトはそれぞれのクラスに属している
p "a".class # String
p 1.class # Integer
p 1.1.class # Float
p true.class # TrueClass
p [1, 2, 3].class # Array
p ({x: 1, y: 2}).class # Hash
p :z.class # Symbol
  • クラスとは「オブジェクトの種族を表すもの
  • すべてのオブジェクトは、いずれかのクラスに属している

インスタンス

  • 「クラスに属するオブジェクト」→「そのクラスのインスタンス」であるとも表現できる
  • インスタンスはオブジェクトとほぼ同じ意味で使うが
    • 「クラスから作ったオブジェクトである」「そのクラスに属する」ことを強調したい時に使う

各クラスに用意されたメソッド

  • 各種オブジェクトは、それぞれが所属するクラスが用意するメソッドを利用できる
p 1.even?
# false
p 2.even?
# true
p [2].even?
# undefined method `even?' for [2]:Array (NoMethodError)

リファレンスマニュアルの使い方

  • リファレンスマニュアルは、クラスごとにメソッド一覧が書かれている
    • 以下の方法で目的にリーチすると良い
  1. class メソッドで所属するクラスを特定
  2. リファレンスで当該のクラスの中からメソッドを探す

オブジェクトを作る 2 つの方法

  • 基本的な方法
a = 1 # Integer オブジェクト
b = "hoge" # String オブジェクト

new メソッドを使ったオブジェクト作成

  • クラス名.newそのクラスのオブジェクトを作る
    • クラスから作られたオブジェクト → インスタンス
  • クラスを new メソッドで呼び出すことで、そのクラスのオブジェクト(インスタンス)が作られる
    • メソッド引数なしの場合、それぞれの空のオブジェクトが生成される
    • メソッドに引数を渡すと、それぞれのオブジェクトが生成される
  • Integer クラスには new メソッドは無い
p String.new # ""
p String.new("hoge") # "hoge"
p Array.new # []
p Array.new(2, "fuga") # ["fuga", "fuga"]

クラスは自作できる

  1. 「こんな機能を持ったオブジェクトがあったら便利だな」といった場面でクラスを自作する
  2. そのクラスのオブジェクトを作り、使うことでプログラムを整理して各ことができる
  • クラスはその種類のオブジェクトを作ることができる工場のようなもの
    • そのクラス自身が仕事をすることもあれば、そのクラスから作ったオブジェクトが仕事をすることもある

クラスの定義

class クラス名
end
  • 簡単に定義できるが、これだけで newclass といったメソッドを使うことができる
class Drink
end

drink = Drink.new # 1.
p drink.class # 2.
  1. new メソッドで Drink クラスのオブジェクトを作り、変数 drink に代入
  2. drinkclass メソッドを使ってクラス名を確認

クラス名の規則 キャメルケース

  • クラス名の先頭は大文字、2 文字目以降は小文字にする
    • Drink Item
  • 2 語以上の単語になる場合は、キャメルケースを使う
    • CaffeeLatte ListGenerate

余談:クラス名は定数

  • 定数は大文字から書き出す
  • 定数は変数と違い、(基本的に)上書き変更不可
  • クラスを定義すると、クラス名の定数が作られる

余談:クラスもオブジェクト

  • クラスもオブジェクトなので class メソッドを呼び出すと、どのクラスに属しているかが分かる
class Drink
end

p Drink.class
# Class

クラスにメソッドを定義する

  • クラスは定義しただけでは、newclass といった最低限の機能しかない
  • クラスにメソッドを追加していくことで、欲しい機能を持ったクラスを育てていける
    • クラスに新たなメソッドを追加定義していくことは、ゲームに例えると新しい魔法が増えていく感覚に似ている
class クラス名
  def メソッド名
  end
end

クラスに定義したメソッドの呼び出し

オブジェクト.メソッド

class Drink
  def name
    "coffee"
  end
end

drink = Drink.new # 1.
p drink.name # 2.
# "coffee"
  1. Drink クラスのオブジェクトを作って drink に代入
    クラス名.new → そのクラスのオブジェクトを作る)
  2. Drink クラスのオブジェクト name メソッドを呼び出し
  • クラスに定義したメソッドは、そのクラスに属するすべてのオブジェクトで呼び出すことができる
  • クラスにメソッドを定義しておけば
    1. そのクラスからオブジェクトを作る
    2. そのオブジェクトたち全員がメソッドを呼び出せる

レシーバ

  • レシーバ(受け取る人)
    • 「メソッドを呼び出されるオブジェクト」のこと
  • 以下の例の場合、「(変数 drink に代入された)Drink クラスのオブジェクト」がレシーバになる
class Drink
  def name
    "coffee"
  end
end

drink = Drink.new
  • 2.even?
    • even? メソッドのレシーバは、2(整数オブジェクト)
  • ["a", "b", "c"].size
    • size メソッドのレシーバは、["a", "b", "c"](配列オブジェクト)

methods メソッドを使って利用可能なメソッドを確認できる

  • レシーバであるオブジェクトで呼び出せるメソッドを一覧表示できる
p drink.methods

クラスに引数を受け取るメソッドを定義

class Calc
  def plus(x, y)
    x + y
  end
  def minus(x, y)
    x - y
  end
end

calc = Calc.new

p calc.plus(2, 7) # 9
p calc.minus(7, 24) # -17

クラスの中で同じクラスのメソッドを呼び出す

  • クラスに定義されたメソッドの中で、同じクラス内のほかのメソッドを呼ぶ際は、メソッド名をそのまま書くことで呼び出せる
class Calc
  def plus(x, y)
    x + y + num_100 # 2.
  end
  def minus(x, y)
    x - y
  end
  def num_100
    100
  end
end

calc = Calc.new # 3.

p calc.plus(5, 2) # 1.
# 107
  1. calc.plus → レシーバ (calc) を指定したメソッドの呼び出し
  2. num_100レシーバを省略した書き方
    • 省略すると、実行中の plus メソッドのレシーバである 1. の calc がレシーバとなる
  3. つまり、2. の num_100 のレシーバは、3. で作られた Calc クラスのオブジェクトとなる

self を使ってレシーバを調べる

  • レシーバが何かが分からないときは self を使って調べることができる
    • self は、その場所でメソッドを呼び出したときのレシーバを返す
class Calc
  def plus(x, y)
    p self # 2.
    x + y + add_100
  end
  def minus(x, y)
    x - y
  end
  def add_100
    100
  end
end

calc = Calc.new
p calc # 1.

p calc.plus(5, 2)

# #<Calc:0x000000010ed749c0>
# #<Calc:0x000000010ed749c0>
# 107
  1. クラス Calc から生成されたオブジェクト
  2. self で取得したレシーバ

ともに #<Calc:0x000000010ed749c0> となり、同じオブジェクトを指している

オブジェクトの識別番号

  • : に続く文字列 → オブジェクトの識別番号
  • 0x は共通
  • 識別番号が同じ → オブジェクトが同じ

レシーバを省略しない書き方

  • self でレシーバを取得できることを利用して、レシーバを省略せずに記述すると下記になる
  • x + y + self.add_100