💡 この記事でわかること
- クラスとは何か、インスタンスとの関係
classでの定義、initializeとnewの役割@付きのインスタンス変数と、attr_accessorでの属性の公開- メソッドだけで書く場合との違い、クラスを使うメリット
- 継承(
<)とsuper、moduleによるミックスインの基本
1. クラスとは?
クラスとは、
👉 データ(属性)と処理(メソッド)をひとまとめにした「設計図」です。
💡 設計図であるクラスから、実際に使う「実体」を作ります。この実体をインスタンスと呼びます。たとえば「犬」という設計図(クラス)から、「ポチ」「ハチ」といった個々の犬(インスタンス)を作る、というイメージです。
これまで使ってきた文字列や配列も、実は String クラス・Array クラスのインスタンスです。「Rubyはすべてがオブジェクト」というのは、あらゆる値が何かのクラスから作られている、という意味でした。
👉 Rubyのデータ型(.classで型を調べる)についての記事はこちら
2. クラスを定義する(class・initialize・@)
class Dog
def initialize(name, age)
@name = name # インスタンス変数(このインスタンスの名前)
@age = age # インスタンス変数(このインスタンスの年齢)
end
def bark
puts "#{@name}がワンと鳴きました"
end
endclass クラス名〜endで定義する。クラス名は大文字始まり(UserProfileのようなキャメルケース)が慣習initializeは、インスタンスを作るときに自動で呼ばれる初期化用のメソッド@nameのように@で始まる変数をインスタンス変数といい、そのインスタンスの中ならどのメソッドからでも使える
👉 Rubyではメソッドの引数に self を書く必要はありません(PythonやJavaScriptとの違いです)。「そのインスタンス自身のデータ」は @ を付けた変数で表します。@ の付かないふつうの変数は、そのメソッドの中だけの一時的な変数です。
3. インスタンスを作って使う(new)
pochi = Dog.new("ポチ", 3) # インスタンスを作成(initialize が呼ばれる)
hachi = Dog.new("ハチ", 5)
pochi.bark # ポチがワンと鳴きました
hachi.bark # ハチがワンと鳴きました💡 クラス名.new(引数) でインスタンスを作れます。このとき渡した引数が initialize に渡ります。pochi と hachi は同じ Dog クラスから作られていますが、それぞれ別の名前・年齢を持っています。
4. 属性を外から扱う(attr_accessor)
👉 インスタンス変数(@name)は、クラスの外から pochi.name のように直接読み書きできません。外から扱えるようにするには、専用のメソッドが必要です。
Rubyには、そのメソッドを自動で用意してくれる便利な書き方があります。
attr_reader :name:読み取り専用(pochi.nameで読める)attr_writer :name:書き込み専用(pochi.name = "…"で変更できる)attr_accessor :name:読み書き両方
class Dog
attr_accessor :name
attr_reader :age
def initialize(name, age)
@name = name
@age = age
end
end
pochi = Dog.new("ポチ", 3)
puts pochi.name # ポチ(読める)
pochi.name = "ポチ2世" # 変更できる
puts pochi.age # 3(読めるが、変更はできない)💡 「外から見せたいものだけ attr_* で公開する」のが基本です。内部の計算用データなど、外から触られたくないものは @ のままにしておきます。これがオブジェクト指向でいう「カプセル化」です。
5. 使用例:買い物カゴ
「データ」と「そのデータを操作する処理」がセットになっている例として、買い物カゴをクラスにしてみます。
class Cart
def initialize
@items = [] # 商品を入れる配列
end
def add(item)
@items << item
end
def count
@items.size
end
def list
@items.join("、")
end
end
cart = Cart.new
cart.add("りんご")
cart.add("パン")
puts cart.count # 2
puts cart.list # りんご、パン👉 カゴの中身(@items)と、それを操作するメソッド(add・count・list)が1つのクラスにまとまっています。使う側は cart.add(...) と書くだけで、内部で配列をどう管理しているかを気にせず済みます。
👉 クラスの中でよく使う、配列・ハッシュについての記事はこちら
6. メソッドだけの場合との違い
| メソッド(関数)だけ | クラス | |
|---|---|---|
| まとめるもの | 処理だけ | データ(属性)と処理(メソッド)をセット |
| 状態(データ)の保持 | 基本は持たない | インスタンスごとに持てる |
| 向いている場面 | 入力→出力が明確な処理 | 「モノ」を表現し、状態を持たせたいとき |
👉 小さな処理はまずメソッドで十分です。「関連するデータと処理がいくつも増えてきて、まとめて扱いたい」と感じたときにクラスを検討しましょう。
👉 Rubyのメソッド(def・引数・戻り値)についての記事はこちら
7. 継承(他のクラスを引き継ぐ)
継承を使うと、あるクラスの機能を引き継いだ新しいクラスを作れます。Rubyでは class 新クラス < 元クラス と、< 記号で書きます。
class Animal
def initialize(name)
@name = name
end
def speak
puts "#{@name}が鳴きました"
end
end
class Cat < Animal # Animal を継承する
def speak # 同じ名前のメソッドで上書き(オーバーライド)
puts "#{@name}がニャーと鳴きました"
end
end
Animal.new("どうぶつ").speak # どうぶつが鳴きました
Cat.new("タマ").speak # タマがニャーと鳴きました💡 オーバーライドしたメソッドの中で super と書くと、元のクラスの同名メソッドを呼び出せます。「元の処理に少し足したいだけ」のときに使います。
class Dog < Animal
def initialize(name, breed)
super(name) # Animal の initialize(@name の設定)を実行
@breed = breed
end
end👉 継承は便利ですが、深くしすぎると複雑になります。最初は「共通処理を親クラスにまとめる程度」に留めるのがおすすめです。
8. module(ミックスイン)
前回の記事で「module は名前をまとめる箱」と紹介しました。もう1つの使い方がミックスインです。複数のメソッドを module にまとめ、クラスの中で include すると、そのクラスにメソッドを「混ぜ込む」ことができます。
module Greetable
def greet
puts "こんにちは、#{name}です"
end
end
class User
include Greetable # Greetable のメソッドを取り込む
attr_reader :name
def initialize(name)
@name = name
end
end
User.new("太郎").greet # こんにちは、太郎です💡 Rubyは「1つのクラスは1つの親しか継承できない」代わりに、module はいくつでも include できます。共通機能を親子関係にせず横から足せるのが、ミックスインの利点です。標準ライブラリの Comparable や Enumerable も、この仕組みで提供されています。
👉 Rubyのライブラリ(require・moduleという言葉の意味)についての記事はこちら
9. クラス用語 早見表
| 用語 | 意味 |
|---|---|
| クラス | 設計図(class 〜 end で定義) |
| インスタンス | 設計図から作った実体(Dog.new("ポチ", 3)) |
| initialize | new のときに自動で呼ばれる初期化メソッド |
| インスタンス変数 | @name のように @ で始まる、そのインスタンスのデータ |
| attr_accessor など | インスタンス変数を外から読み書きするメソッドを自動生成 |
| 継承 | class Cat < Animal。親の機能を引き継ぐ |
| super | オーバーライド元(親)の同名メソッドを呼ぶ |
| module / include | メソッドのまとまりをクラスに混ぜ込む(ミックスイン) |
10. まとめ
- クラスはデータと処理をまとめた設計図。
クラス名.newでインスタンスを作る initializeで初期化、そのインスタンスのデータは@付きの変数で持つ@は外から直接触れない。attr_reader/attr_accessorで見せたいものだけ公開する- 小さな処理はメソッドで十分。状態を持つ「モノ」を表したいときにクラス
- 継承は
<、親の呼び出しはsuper。module+includeで機能を混ぜ込める
👉 まずは initialize で属性を2〜3個持ち、メソッドを1つ作る、という小さなクラスから書いてみましょう。Ruby on Rails では、モデル・コントローラなどすべてがクラスで書かれています。ここで基本をつかんでおくと、フレームワーク学習がぐっとスムーズになります。