はじめに
@nqounetです。
新しいシリーズ「本棚アプリで覚える集合体の巡回」を始めます。
このシリーズでは、蔵書を管理する本棚アプリを題材に、オブジェクト指向プログラミングの実践的なテクニックを学んでいきます。単なる文法の解説ではなく、実際に動くアプリケーションを作りながら、設計の考え方を身につけることを目指します。
このシリーズについて
対象読者
- Perl入学式を卒業したばかりの方
- 「Mooで覚えるオブジェクト指向プログラミング」シリーズを読了した方
- クラスの作り方は分かるが、複数のオブジェクトを効率的に扱う方法を学びたい方
前提知識
- Perlの基本的な文法(変数、配列、ハッシュ、サブルーチン)
- Mooを使ったクラスの定義方法(
has、subの基本) - オブジェクトの生成と利用(
newメソッド)
まだMooの基礎が不安な方は、先に「Mooで覚えるオブジェクト指向プログラミング」シリーズをご覧ください。
技術スタック
- Perl v5.36以降(signatures対応)
- Moo(CPANモジュール)
今回学ぶこと:集合体(Aggregate)の基本
プログラムを書いていると、同じ種類のオブジェクトを複数まとめて管理したい場面がよくあります。
今回作成するクラス構成を先に示します。
classDiagram
class Book {
+title
+author
}
class BookShelf {
-books
+add_book(book)
+get_book_at(index)
+get_length()
}
BookShelf "1" o-- "*" Book : contains
例えば、本棚には複数の本があります。音楽プレイヤーにはプレイリストがあり、その中には複数の曲が入っています。掲示板には複数の投稿があります。
このように、複数の要素をまとめて管理するオブジェクトのことを「集合体(Aggregate)」と呼びます。
今回は、本棚アプリを作りながら、この集合体の基本的な考え方を学んでいきます。
Bookクラスを作る
まずは、本を表すBookクラスを作りましょう。本には「タイトル」と「著者」があります。
| |
このコードのポイントは以下の通りです。
is => 'ro'— 読み取り専用(read-only)の属性を定義する。一度設定した値は変更できないrequired => 1— オブジェクト生成時に必ず値を指定する必要がある
本のタイトルや著者は、後から勝手に変わってほしくないですよね。そのため、rw(read-write)ではなくro(read-only)を指定しています。
BookShelfクラスを作る
次に、本を管理する本棚クラスを作ります。本棚は複数の本を持ち、本の追加や取得ができます。
| |
このコードのポイントは以下の通りです。
default => sub { [] }— デフォルト値として空の配列リファレンスを設定する。sub { ... }で囲むのは、オブジェクトごとに新しい配列を作成するため$self->books->@*— 配列リファレンスを配列として展開する(postfix dereference記法)add_book— 本棚に本を追加するメソッドget_book_at— 指定した位置の本を取得するメソッドget_length— 本棚にある本の数を返すメソッド
BookShelfクラスは、内部にbooksという配列を持ち、その配列を通じて複数のBookオブジェクトを管理しています。これが「集合体」の基本的な形です。
完成コード
以上をまとめた完成コードを以下に示します。このコードをbookshelf.plとして保存し、実行してみましょう。
| |
実行方法
| |
実行結果
| |
まとめ
- 集合体(Aggregate)は、複数のオブジェクトをまとめて管理するオブジェクトである
Bookクラスは個々の本を表し、titleとauthorの属性を持つBookShelfクラスは本の集合体であり、add_book、get_book_at、get_lengthメソッドを提供する- 属性を
ro(読み取り専用)にすることで、意図しない変更を防げる
次回予告
今回作った本棚アプリでは、forループとget_book_atを使って本を順番に取り出しました。しかし、この方法には問題があります。本棚の内部構造(配列であること)を外部から知っている必要があるのです。
次回は、本棚の内部構造を知らなくても本を順番に取り出せる仕組みを作ります。「イテレータ」という概念を学びましょう。
お楽しみに。
