プログラミングをチームで効率よく開発するためには、担当領域を決めたり、似たようなコードが作らないようにするなどの工夫が必要となります。
プログラムを役割や機能に応じて分割することをモジュール分割と言ったりしますが、その際に必要となる概念がクラスです。
適切なクラス分割を行うことで、無駄がなくて読みやすく、メンテナンスのしやすいプログラムにすることができます。
プログラミング初心者にとっては、理解が難しい分野ではありますが、チームで開発するプログラマとなるためには必須の知識となります。
本記事では、Rubyのクラスと継承についてまとめます。
プログラミング初心者の方の学習や、忘れてしまった方の復習として、参考にしていただければ幸いです。
記載しているプログラムは、Ruby2.7.1を使って動作確認をしています。
Rubyのクラスと継承
Rubyのクラスと継承について、以下の内容を採り上げます。
- クラスの定義方法
- コンストラクタ
- インスタンス化
- インスタンスメソッド
- インスタンス変数
- クラスメソッド
- クラス変数
- クラスの継承
クラスの定義方法
クラスとは、動作(メソッド)や状態(プロパティ)を持つ構造(オブジェクト)です。
クラスを定義するには、class キーワードによって宣言します。
例えばPersonクラスを宣言するには、以下のように記述します。
class Person end
コンストラクタ
コンストラクタは、そのクラスからインスタンスを作成(後述)した際に、最初に実行されるメソッドです。
通常はクラスの初期化処理を記述するために用いられます。
コンストラクタを定義するには、initialize メソッドを定義します。
class Person def initialize end end
インスタンス化
定義したクラスを利用するためには、インスタンス化する必要があります。
インスタンス化とは実体を作ることで、クラス定義は実体を作るための雛形やテンプレートのようなものであり、インスタンス化すると実物が作成されるというイメージです。
インスタンス化するにはクラスを new メソッドで呼出します。
以下の例では、Personクラスをインスタンス化して、personという変数に代入しています。
person = Person.new
インスタンスメソッド
クラスにおけるメソッドの役割は、そのクラスの動作(振る舞い)を定義するものになります。
例えば、Person(人間)クラスであれば、歩く、食べる、寝るという動作がクラスとしてのメソッドになります。
Rubyでは、インスタンス化して呼出す通常メソッドをインスタンスメソッドと呼びます。
class Person def walk puts "歩きます" end def eat puts "食べます" end end
上記のクラス定義をインスタンス化して実行すると、以下のようになります。
インスタンスメソッドの実行は、インスタンスを作成する必要があります。
person = Person.new person.walk # -> 歩きます person.eat # -> 食べます
インスタンス変数
インスタンス自身が保持する変数をインスタンス変数と呼びます。
Rubyでは、変数名の前に @ を付けて定義し、コンストラクタで設定したり、各インスタンスメソッドから操作することができます。
コンストラクタで設定
コンストラクタの引数で設定したい値を受取り、インスタンス変数に代入します。
class Person def initialize(age) @age = age end def say_age puts "年齢は#{@age}歳です" end end
上記のクラス定義をインスタンス化する際に、引数にインスタンス変数に設定する値を指定します。
person = Person.new(30) person.say_age # -> 年齢は30歳です
アクセッサで設定
インスタンス変数は、外部から自由に値を書き換えたり、参照することができないようになっています。
アクセッサを定義することで、外部からの変更や参照を許可することができます。
class Person attr_accessor :age def initialize(age) @age = age end end
上記のプログラムでは、ageというインスタンス変数に対してアクセッサを定義しています。
対象の変数に、attr_accessor というアクセッサメソッドを定義することで、変更・参照が可能となります。
同様のアクセッサメソッドとして、変更のみ可能な attr_writer 、参照のみ可能な attr_reader があります。
値を取得するattr_readerを getter、値を設定する attr_writer を setter と呼びます。
上記のクラス定義をインスタンス化して、値を設定し、取得すると以下のようになります。
person = Person.new(30) person.age = 20 puts person.age # -> 20
setterでロジックによって値をチェックする場合は、自分でメソッドを実装する必要があります。
例えば、年齢が負の値に変更されるのはおかしいため、0以上である場合のみインスタンス変数に設定したいというような場合です。
クラスメソッド
インスタンスメソッドとは異なり、インスタンス化しなくても呼び出せるクラスメソッドを定義することができます。
クラスメソッドを定義するには、メソッド名の先頭 self を付けます。
class Person def self.say_hello puts "Hello" end end
クラスメソッドからは、メソッド外で定義されたインスタンス変数にはアクセスできますが、コンストラクタ等の別メソッド内で定義されたインスタンス変数にはアクセス出来ない点に注意が必要です。
上記のクラスメソッド say_hello を呼出すには、インスタンス化する必要はありません。
Person.say_hello # -> Hello
クラス変数
静的メソッドと同様に、インスタンス化しなくてもアクセスできるクラス変数を定義することができます。
クラス変数を定義するには、変数名の先頭に @@ を付けます。
class Person @@class_name = "人間" def self.say_hello puts "Hello, #{@@class_name}です" end end
クラス変数は、クラスメソッドやインスタンスメソッドからアクセスすることが可能です。
外部からアクセスすることはできません。
値を書き換えると、全インスタンスに影響を与える点に注意が必要です。
Person.say_hello # -> Hello, 人間です
クラスの継承
クラスの継承とは、あるクラスを引き継いで新たなクラスを定義することです。
引き継ぎ元のクラスを親クラス(基底クラス、スーパークラス)と呼び、引き継ぎ先のクラスを子クラス(派生クラス、サブクラス)と呼びます。
子クラスを定義するには、< の後に親クラスを指定して、以下のように定義します。
class Child < Person end
子クラスは親クラスのメソッドや変数を継承しているため、そのまま呼出すことができます。
child = Child.new(1) child.walk # -> 歩きます puts child.age # 1
親クラスが持つメソッドを同じメソッド名で処理を書き換える(オーバーライド)こともできます。
例えば、walkメソッドを以下のようにオーバーライドします。
class Child < Person def walk puts "ハイハイします" end end
インスタンス化して、walkメソッドを呼出すと以下のようになります。
child = Child.new(1) child.walk # -> ハイハイします
親クラスが持つメソッドは、super を使って呼出すことができます。
class Child < Person def eat print "たくさん" super end end child = Child.new(1) child.eat # -> たくさん食べます
良いプログラマになるにはクラス設計が重要
プログラマは単にプログラミングするだけではなく、設計ができることも重要です。
チームで効率よく開発を進めるには、どんなクラス設計、継承関係、クラス間連携とするのかは重要な要素です。
クラス分割をしたり、オブジェクト指向でプログラミングするのは難しいかもしれませんが、普段から目に見えるものがどんな関係があるか、どんな振る舞いを持っているのかを考えてみると良い訓練になると思います。
今回はRubyのクラスと継承についてまとめました。
以上、参考になれば幸いです。
コメント