結局、なんでオブジェクト指向で作るんだっけ?

あれこれ学ぶ
Photo by Domenico Loia on Unsplash

最近は困ったらググるよりChatGPTくんに教えてもらうことが増えましてねぇ。

なぜオブジェクト指向で作ると開発が楽になるの?

オブジェクト指向プログラミング(OOP)は、開発プロセスを楽にし、コードの品質を向上させるいくつかの理由があります。主な利点は以下の通りです。

再利用性: オブジェクト指向プログラミングでは、コードをクラスとオブジェクトの形式で構造化します。これにより、一度書いたコードを他のプロジェクトでも再利用しやすくなります。同様の機能を持つ新しいオブジェクトを作成する際に、既存のクラスを継承してコードを再利用できます。

モジュール性: オブジェクト指向プログラミングでは、各クラスやオブジェクトは特定の機能や責任を持ちます。これにより、プログラム全体が独立したモジュールに分割され、各モジュールが互いに連携して動作します。モジュール性が高いと、コードの修正や拡張が容易になり、複雑なプロジェクトでも管理しやすくなります。

可読性と保守性: オブジェクト指向プログラミングは、コードをより構造化し、理解しやすくするのに役立ちます。各クラスやメソッドには明確な目的があり、それぞれが独立して機能するため、コードの可読性が向上します。また、コードの保守性も向上し、バグの修正や機能の追加が容易になります。

カプセル化: オブジェクト指向プログラミングでは、データとメソッドをクラス内にカプセル化することで、外部からのアクセスを制限できます。これにより、データの整合性が保たれ、意図しないデータの変更や破損を防ぐことができます。

柔軟性: オブジェクト指向プログラミングのポリモーフィズム機能により、異なるクラスのオブジェクトを同じインターフェイスで扱うことができます。これにより、プログラムの柔軟性が向上し、新しい機能の追加や既存機能の変更が容易になります。

この辺は調べれば同じような記事はたくさん見つかる。言葉として知ってはいるけど、いまいち自分の中に落ちた感じが無い。

再利用性の高さがメリットになるのはどういう時?

再利用性の高さがメリットになるのは、以下のような状況です。

共通機能の利用: よく使われる共通機能を一度実装しておくことで、他のプロジェクトやプログラムでもその機能を簡単に利用できます。これにより、同じコードを繰り返し書く手間が省け、開発効率が向上します。

コードの品質向上: 既存のコードを再利用することで、そのコードの品質が検証され、信頼性が高まります。再利用されるコードは、多くのプロジェクトで使われるため、バグが発見されやすく、修正も迅速に行われることが期待できます。

開発時間の短縮: 再利用可能なコードがあることで、新しい機能の開発や既存機能の修正にかかる時間を大幅に短縮できます。これにより、開発サイクルが短くなり、より迅速に新しい機能をリリースできるようになります。

標準化と統一性: 再利用性の高いコードは、開発チーム全体で共有されることが多いため、コードの標準化や統一性が向上します。これにより、チーム内でのコミュニケーションが円滑になり、コードの保守や拡張が容易になります。

学習コストの削減: 既存のコードを再利用することで、新しい技術やフレームワークを習得する学習コストが削減されます。また、再利用性の高いコードは、新しいメンバーがプロジェクトに参加した際にも理解しやすくなります。

これらのメリットを活かすために、開発チームは再利用性の高いコードを作成し、共有することを心がけることが重要です。オブジェクト指向プログラミングは、再利用性を向上させるための構造化とカプセル化の概念を提供しており、適切に活用することで開発効率が大幅に向上します。

再利用性とカプセル化は並列に存在するわけではなく、カプセル化することで再利用性が高まるってことですね。それ以外の部分に関しても、特に疑問はわかない。

カプセル化することの最大のメリットは?

カプセル化にはいくつかのメリットがありますが、最大のメリットは、データの保護と整合性の確保です。

カプセル化により、クラス内のデータとメソッドを隠蔽し、外部から直接アクセスできなくなります。これにより、以下のような利点が得られます。

データの保護: クラス内のデータを外部から直接変更できないようにすることで、意図しないデータの変更や破損を防ぐことができます。データへのアクセスは、クラスが提供するメソッドを通じてのみ可能となり、アクセスが制御されます。

整合性の確保: クラス内のデータにアクセスする際には、メソッドを介して行うため、データの整合性を保つロジックが一元化されます。これにより、データの不整合が発生しにくくなり、プログラム全体の安定性が向上します。

コードの保守性向上: カプセル化により、クラスの内部実装が隠蔽されるため、内部実装を変更しても外部に影響を与えにくくなります。これにより、コードの保守や拡張が容易になり、開発効率が向上します。

簡潔で分かりやすいインターフェイス: カプセル化によって、クラスが提供するインターフェイスが簡潔で分かりやすくなります。これにより、他の開発者がそのクラスを使用する際に、内部の詳細を理解することなく、提供されるメソッドを利用できます。

これらのメリットにより、カプセル化はオブジェクト指向プログラミングにおいて重要な概念となっており、データの保護や整合性の確保、コードの保守性向上など、プログラム全体の品質を向上させる役割を果たしています。

データの保護が必要というのは理解できるけど、よく聞くgetter/setterってこのデータの保護を破るんじゃないの?

内部実装が隠蔽されることで外部に影響を与えない、というのをわかりやすく説明できる?

もちろんです。内部実装が隠蔽されることで外部に影響を与えないという概念を、以下の例を使って説明します。

例えば、銀行の口座管理システムを考えます。口座に関するクラス BankAccount があり、このクラスには口座残高を保持する変数 balance があります。また、このクラスには預金を行うメソッド deposit と引き出しを行うメソッド withdraw があります。

このクラスをカプセル化することで、以下のような効果が得られます。

balance 変数に直接アクセスできないため、意図しない変更や破損を防ぐことができます。
deposit や withdraw メソッドを介してのみ、口座残高を操作できるため、データの整合性を保つことができます。
これにより、BankAccount クラスの内部実装を変更しても、外部から deposit や withdraw メソッドを使ってアクセスする限り、影響は受けません。

例えば、内部実装で balance の計算方法を変更しても(例えば、通貨の変更や複数の通貨をサポートするようにする)、外部からは deposit や withdraw メソッドを使って操作するだけなので、その変更に対して無関係なコードを変更する必要はありません。

このように、内部実装が隠蔽されることで、コードの保守性が向上し、クラスの利用者は実装の詳細を知らずにインターフェイスを利用できます。これが、カプセル化によって外部に影響を与えないという概念です。

なるほど、特定のメソッドを使わないと操作できないようにして、中の変数にも直接アクセスできないようにして、なおかつこのクラスを変更してもメソッド名さえ一緒なら他を修正する必要が無いということですね。銀行口座の例はたしかにわかりやすい。

全然関係ないけど、もちろんですって言ってくれるのかわいい。

いわゆるgetter/setterと、depositやwithdrawは何が違うの?

getterとsetterは、オブジェクト指向プログラミングにおいて、クラスのプロパティ(変数)にアクセスするための特別なメソッドです。これらのメソッドを使用することで、直接プロパティにアクセスするのではなく、メソッドを介してアクセスを行うことができます。これにより、カプセル化の原則が守られ、データの保護や整合性が保たれます。

depositやwithdrawは、特定の操作を行うためのカスタムメソッドです。これらのメソッドは、通常、特定のロジックや制約を持っており、オブジェクトの状態を変更する処理をカプセル化します。

getter/setterとdeposit/withdrawの違いは以下の通りです。

目的: getterとsetterは、プロパティの取得や設定を行うために使用されます。これに対して、depositやwithdrawは、特定の操作(預金や引き出し)を行うために使用されます。

機能: getterはプロパティの値を返し、setterはプロパティの値を設定します。これらは基本的に単純なアクセス制御を提供します。一方、depositやwithdrawは、ビジネスロジックや操作の制約(例えば、引き出し額が残高を超えないようにする)を実装するために使用されます。

カプセル化の程度: getterとsetterは、プロパティへのアクセスを制御するために使用されるため、ある程度のカプセル化を提供しますが、基本的にはデータの読み書きに焦点を当てています。一方、depositやwithdrawは、操作自体をカプセル化し、オブジェクトの状態を変更するためのロジックや制約を含んでいるため、より強固なカプセル化を提供します。

両者は異なる目的と機能を持っていますが、どちらもカプセル化の原則に従ってオブジェクトの状態を制御し、データの保護と整合性を保つ役割を果たしています。

そもそも自分がgetter/setterの意味を履き違えていたってことか。よくgetter/setterは悪という意見を見るけど、結局は使い方だったり開発の現場の作法だったりで変わるんだろうな。

フィールドの値にアクセスできないと困るケースってある?

フィールドの値にアクセスできないと困るケースは、実際にはあまり多くありません。オブジェクト指向プログラミングの原則に従うと、オブジェクトの内部状態はカプセル化され、外部から直接アクセスされるべきではありません。そのため、アクセス制御を行うために、getterとsetterメソッドが推奨されます。

ただし、以下のようなケースでフィールドに直接アクセスできないと困る場合があります。

パフォーマンス: ゲッターやセッターを介してアクセスすることで、わずかながらオーバーヘッドが発生することがあります。特に高いパフォーマンスが求められる場合や、リソースが制限されている場合、直接アクセスが適切な選択肢となることがあります。

シンプルなデータ構造: シンプルなデータ構造や、メソッドを持たない単なるデータコンテナを作成する場合、フィールドに直接アクセスできるようにすることが適切な場合があります。ただし、これはオブジェクト指向の原則に反することがあります。

互換性: 既存のコードベースやライブラリとの互換性を維持するために、フィールドに直接アクセスできるようにする必要がある場合があります。ただし、これはあまり推奨される方法ではありません。

これらのケースを除いて、一般的にはフィールドに直接アクセスするのではなく、ゲッターやセッターを使用してアクセス制御を行うことが推奨されます。これにより、カプセル化の原則が守られ、データの保護や整合性が保たれます。

データしか持っていないのであれば外部からアクセスできないと何もできないけど、そもそもそういった構造をもつこと自体がオブジェクト指向から外れるということかな?

やっぱりオブジェクト指向は難しいんだけど、まずは何から取り組めばいいかな?一番重要だと思うものを一つだけピックアップして

オブジェクト指向プログラミングを学ぶ際に最も重要なのは、クラスとオブジェクトの理解です。クラスはオブジェクト指向プログラミングの基本単位であり、オブジェクトはクラスから生成されるインスタンスです。クラスとオブジェクトの関係を理解することで、他のオブジェクト指向の概念(継承、ポリモーフィズム、カプセル化など)を学ぶ上での基礎が整います。クラスとオブジェクトを理解し、それらを使ってコードを設計・実装することで、オブジェクト指向プログラミングの基本的な考え方に慣れることができます。

まずはクラスとオブジェクトの理解と。

結局、オブジェクトってなに?

オブジェクトとは、オブジェクト指向プログラミングにおいて、データ(状態)とそれを操作するメソッド(振る舞い)を一つにまとめたものです。オブジェクトは、クラスという設計図から生成されるインスタンスで、実際にプログラムで使用される具体的なデータ構造です。

オブジェクトは、プログラムを現実世界の状況や概念に近い形でモデル化するために使用されます。例えば、自動車のプログラムを考えるとき、自動車を表すオブジェクトがあり、そのオブジェクトには速度や燃料といったデータ(状態)が含まれています。また、そのオブジェクトは、アクセルを踏む、ブレーキをかけるなどの操作を行うメソッド(振る舞い)を持っています。

オブジェクト指向プログラミングでは、複数のオブジェクトが相互作用することでプログラム全体が機能し、状態管理や振る舞いの実装が効率的に行えるようになります。

ただモノであればオブジェクトだと思っていたけど、オブジェクト指向の場合はそのオブジェクトの動きもまとまっている必要があるということですね。

まとめ

具体的にこれをやればオブジェクト指向である、というものではなくいろいろな概念が集まってできたもので、使えれば再利用したり修正が少なくなったりして開発がしやすくなる。

まずはクラスやオブジェクトについて理解するところから始める。

オブジェクト指向じゃないと開発ができないわけではないので、作りながら「このオブジェクトはこういう振る舞いをするべきだよな」とか「ここはカプセル化できてないな」とか考えながら作れればいいのかも。この辺は設計の部分だと思うので、今度は設計関係の本を読んで見ることにしよう。

タイトルとURLをコピーしました