この記事を書いた理由
React v18 以降を中心に開発してきた自分にとって、プログラミングにおける class という概念に触れる機会はほとんどありませんでした。
関数型の考え方は React を通じてある程度理解してきましたが、他のプログラミング言語の視点では、Python の FastAPI を使った API 開発の経験がある程度です。
今後は 言語の壁を乗り越えてスキルを広げていきたい と考えていますが、そのためにはまず 「関数」だけでなく「クラス (class)」の概念も理解しておくべきだ と感じました。
調べていくうちに、「クラスを理解するには、そもそも オブジェクト指向 (OOP) の基礎を押さえることが重要」だと気づいたため、この記事を書きました。
執筆開始時点でのオブジェクト指向に関する理解度
- オブジェクト指向、単語は知ってるけど、意味は正直あんまりわかってない。
「オブジェクト指向」とは
主要なオブジェクト指向に該当する言語
(すべてがオブジェクトとして扱われる。クラスを必須とする設計)
- Java
- C#
- Python
- Ruby
- PHP
などがある。
これらの言語は、「クラス」を基本単位として設計し、すべてがオブジェクトとして扱われる ため、オブジェクト指向プログラミングが必須になります。
オブジェクト指向もできる言語
- JavaScript(クラスを使えるが、関数型や手続き型でも書ける)
- TypeScript(型を強化した JS だが、同じく関数型・手続き型も可能)
- swift/kotlin (クラスベースだが、関数型プログラミングも推奨)
これらの言語は、クラスを使ってオブジェクト指向的に書くこともできるが、関数型や手続き型の書き方も可能 という点で、純粋なオブジェクト指向言語とは異なります。
主要な言語で「オブジェクト指向でない言語」
(オブジェクトの概念がなく、手続き型がメイン)
- C(すべてが手続き的で、オブジェクトの概念なし)
- COBOL(ビジネスロジック向けで、構造化プログラミングが基本)
などがある。
まずオブジェクト指向とは
参照した記事
オブジェクト指向プログラミング(OOP)は、オブジェクト同士のやり取りを軸にしたプログラミング手法 です。
変数やデータ構造、関数などを オブジェクトとして扱うことで、コードを整理しやすくし、再利用性を高める ことが目的とされています。
情報の種類ごとに クラス(設計図)を作成し、必要に応じてオブジェクトを生成することで、開発者は 既存のコードを直接変更せずに新しい機能を追加 できます。
また、バグや修正が必要になった際も、関連するクラスの一箇所を修正すれば済むため、コードの管理や保守がしやすくなるのも大きな特徴です。
とのことでした。
「現実世界のものごとを、プログラムのオブジェクトとして整理する」
車なら「車の属性(メーカー、エンジン、色)」などを持つ、
人なら「名前、出身、血液型」を持つ、これが「クラスの設計図の考え方」になる。
実際のプロジェクトでは、
- どこをオブジェクトとしてまとめるべきか
- オブジェクト同士の関係をどうまとめるべきか
という設計がかなり重要になってくるようです。
これがオブジェクト指向!とは知らなかったのですが個人的な経験で、
React - playwrightでのE2Eテスト自動化を行なっていた際にfor文で回す以下のようなコードを作成していました。
/* このconst usersが、オブジェクト指向の「キモ」*/
const users = [
{ role: "admin", email: "admin@example.com", password: "admin123" },
{ role: "user", email: "user@example.com", password: "user123" },
{ role: "guest", email: "guest@example.com", password: "guest123" },
];
for (const user of users) {
test(`ログインテスト: ${user.role}`, async ({ page }) => {
await page.goto("https://example.com/login");
// ログイン処理
await page.fill("input[name=email]", user.email);
await page.fill("input[name=password]", user.password);
await page.click("button[type=submit]");
// 役割ごとの挙動を確認
if (user.role === "admin") {
await expect(page.locator("#admin-dashboard")).toBeVisible();
} else if (user.role === "user") {
await expect(page.locator("#user-dashboard")).toBeVisible();
} else {
await expect(page.locator("#guest-welcome")).toBeVisible();
}
});
}
オブジェクトとして整理することができているので、万が一ユーザーの権限レベルを追加したいなどがあった場合は、levelとしてプロパティを足すだけで簡単に対応が可能になります。
const users = [
{ role: "admin", email: "admin@example.com", password: "admin123", level: 10 }, //levelが追加されている
{ role: "user", email: "user@example.com", password: "user123", level: 5 }, //levelが追加されている
{ role: "guest", email: "guest@example.com", password: "guest123", level: 1 }, //levelが追加されている
];
- 「テストの対象」を「オブジェクト」として整理することで、管理がしやすくなった。
- 「共通処理をまとめて使い回す」ことで、コードがシンプルになった。
⇨意識せずに書いていたつもりでも、実際はオブジェクト指向的な最適化ができていた。
この、「オブジェクトのデータ構造」がオブジェクト指向の本質!!
「データ = オブジェクト」として扱うことで、整理しやすく、管理しやすく、拡張しやすくなる!」
OOP (オブジェクト指向) の本質は「データをオブジェクトとして整理し、それを適切に管理すること」の、「考え方」!!!!
疑問に思ったことがあったのでchatGPTに聞いてみた。
【指向】 《名・ス他》 する事が初めからその方向を指して向かうこと。
「オブジェクト指向」の「指向」は、スタートがオブジェクトなのか、ゴールがオブジェクトなのか?」
「どこに向かうか」という意味だから、オブジェクト指向は「オブジェクトを中心に考える」という考え方を指している。つまり、「スタート(思考の起点)もオブジェクトであり、ゴール(設計の着地点)もオブジェクト」という意味合いになる。
そういう意味か!!!!!!!!!!
今後関連記事にする予定の内容。
書き次第リンクに追加していきます。
- classとは
- オブジェクト指向の三要素「カプセル化, 継承, ポリモーフィズム」
その他「これ学んどけ」みたいなものがありましたらぜひコメントいただけると嬉しいです。
最後に
本当はclass宣言の取り扱いについて書いてみたかったのですが、学習していくにつれてまずはオブジェクト指向を学ばないとダメだとわかったため、急遽内容をシフトしてこの記事となりました。
継続発信で基礎を固めていきたいと思います、ありがとうございました。