はじめに

クラスはうまく作れるようになりましたか?
クラスには、もうひとつ重要な機能があります。
それは、「サブクラス」です。
サブクラスとは、クラスに親子関係を持たせるようなもので、親のメソッドをそのまま引き継ぐことができます。
この機能を使えば、似たようなクラスを量産しなくても済むようになります。
この記事では、Ruby初心者の方向けに、Rubyでのサブクラスの扱い方についてお伝えしていきます。
クラスとともに覚えておきましょう。

クラスのおさらい

はじめに、前回のクラスのおさらいをしておきましょう。
クラスには、次のように「インスタンス変数」と「インスタンスメソッド」を持たせることができるのでした。
例:

class Animal
    def initialize(name)
        @name = name
    end
    def type
        self.class.to_s
    end
    def call
        puts "My name is #{@name}"
    end
end

この例では、”@name変数”と”typeメソッド”および”callメソッド”を定義しています。
特殊な”initializeメソッド”は、次のようにオブジェクトを生成したときに自動的に呼び出されます。
また、selfは、オブジェクト(インスタンス)自身を指します。
例:

a = Animal.new("Peko")
puts a.type
a.call

ここでは、”newメソッド”でオブジェクトを生成して、”変数a”に割り当てています。
”newメソッド”に渡された引数が、そのまま”initializeメソッド”に渡されることを覚えておきましょう。
このため、”@name変数”に”Peko”が割り当てられます。
それから、オブジェクトを割り当てた変数を通じて、”typeメソッド”および”callメソッド”を呼び出しています。
それでは、このクラスを元にサブクラスを作ってみましょう。

サブクラスを作ってみよう

サブクラスを作るには親のクラスが必要なので、先ほどの”Animalクラス”を親(スーパークラス)としてサブクラスを作ってみましょう。
それには、次のようにします。
例:

class Dog < Animal
    def call(number_of_times)
        super()
        puts "bow!" * number_of_times
    end
end
class Cat < Animal
    def call(number_of_times)
        super()
        puts "mew!" * number_of_times
    end
end

この例では、”Animalクラス”をスーパークラスとして、”Dogクラス”と”Catクラス”を定義しています。
ここではスーパークラスの”callメソッド”をオーバーライド(上書き)しています。
ただ上書きするだけでなく、”superキーワード”を使ってスーパークラスの同名メソッドを呼び出しています。
元の”callメソッド”には引数がなく、そのまま”super”とすると自動的に引数が渡されてしまうため、明示的に”()”をつけて呼び出しています。
それから、サブクラス独自の処理を入れています。
それでは、この2つのサブクラスを使ってみましょう。
次のようにします。
例:

d = Dog.new("Taro")
puts "Type: #{d.type}"
d.call(2)
c = Cat.new("Shiro")
puts "Type: #{c.type}"
c.call(3)

この例では、スーパークラス(Animal)から継承された、”typeメソッド”を呼び出しています。
”typeメソッド”内では、”self”を使っているため、呼び出し元のオブジェクトによって出力されるクラス名が変化するのがお分かりになるでしょう。
また、オーバーライドした”callメソッド”についてもみてみましょう。
定義どおり、スーパークラス(Animal)の”callメソッド”が呼ばれた後に、サブクラス独自の処理が入っていることが確認できますね。
このように、サブクラスを活用すれば、スーパークラスのメソッドをそのまま引き継いだり、上書きしてカスタマイズしたりできます。しかし、乱用は禁物です。

サブクラスの乱用は避けよう

オブジェクト指向をよく理解していないと、似たようなクラスをなんでもサブクラスにしてしまいがちです。
サブクラスは、メソッドを再利用する方法ではありません。
同じメソッドが使えるからといった理由で、安易にサブクラス化してはいけません。
基本的に、スーパークラスとそのサブクラスは「is-a関係」になっているべきです。
つまり、”サブクラスはスーパークラスでもある”という関係が成り立つかということです。
先ほどの例でいうと、”サブクラス(Dog、Cat)はスーパークラス(Animal)である”という関係が成り立っています。
スーパークラスとサブクラスの関係性に注意しないと、おかしな継承関係が生まれてしまいます。
後々問題を引き起こす可能性が高くなるので、サブクラスの乱用には気をつけましょう。

まとめ

サブクラスの作り方はお分かりになりましたか?
サブクラスを作るのはとても簡単なので、ついつい乱用しがちですが、ちょっと似ているからといってなんでもサブクラスにすればいいというわけではありません。
オブジェクト指向の”is-a関係(〜は〜である)”を守り、適切な継承関係を築きましょう。