オブジェクト指向プログラムの構造を調べる

完了

オブジェクト指向プログラミング (OOP) では、オブジェクトを使用して実際のエンティティをモデル化します。

構造化プログラミングに慣れている開発者にとって、構造化プログラミングとオブジェクト指向プログラミングの比較は、2 つのアプローチの違いを明確にするのに役立ちます。 さらに、カプセル化とクラスのライフサイクルに関する理解を深め、セキュリティで保護された堅牢なソリューションを開発するのに役立ちます。

Object-Oriented プログラミングと構造化プログラミングの比較

構造化プログラミングとオブジェクト指向プログラミング (OOP) は、ソフトウェア開発に対する 2 つの異なるアプローチであり、それぞれに独自の一連の原則と手法があります。 構造化プログラミングは、プログラムがより小さく、管理しやすい関数またはプロシージャに分割されるトップダウン アプローチに基づいています。 このアプローチでは、ループ、条件、サブルーチンを使用して、制御の明確で論理的なフローを強調します。 オブジェクト指向プログラミングは、データと動作の両方をカプセル化するオブジェクトに関するソフトウェア設計を整理し、よりモジュール化された再利用可能なコード構造を促進します。 構造化プログラミングでは、実行する一連のアクションに重点を置いていますが、オブジェクト指向プログラミングでは、アクションに関連するオブジェクトが強調されます。

構築プロジェクトの実際の例をメタファーとして使用して、構造化プログラミングとオブジェクト指向プログラミングの違いを示すことができます。

Object-Oriented プログラミングの例

都市の設計と構築としてのオブジェクト指向プログラミングを想像してみてください。 このメタファーでは、各建物はクラスを表し、各建物の部屋と施設はそのクラスのプロパティとメソッドを表します。 都市がさまざまな建物で構成されているのと同様に、それぞれが特定の目的 (住宅、商業、工業) を提供する OOP プログラムは、それぞれ特定のタスクを処理するように設計されたさまざまなクラスで構成されています。 建物 (クラス) はブループリント (クラス定義) に基づいて構築され、各建物は同じ構造を共有するが異なる状態 (データ) を持つ複数のインスタンス (オブジェクト) を持つことができます。

この都市では、カプセル化は、その内部構造を保護し、指定されたドアと窓(方法)を介してのみアクセスを許可する建物の壁のようなものです。 カプセル化により、建物 (クラス) の内部作業が外部から隠され、建物との相互作用が制御され、安全になります。

この都市建築のメタファーは、OOPのモジュール式で再利用可能な性質を強調しています。各クラス(建物)を個別に開発、テスト、保守することができますが、それらはすべて連携してまとまりのある機能都市(プログラム)を形成します。 適切に計画された都市で効率的な管理とスケーラビリティが可能になるのと同様に、適切に設計された OOP プログラムにより、保守性、柔軟性、スケーラビリティが促進されます。

構造化プログラミングの例

キルトを作るように構造化されたプログラミングを想像してみてください。 このメタファーでは、ファブリックの各部分は、プログラム内の関数またはプロシージャを表します。 キルトが一緒に縫われた多くの個々のパッチで構成されているのと同様に、構造化されたプログラムは、特定のタスクを実行するように設計されたさまざまな機能で構成されています。 各関数は、個別に開発、テスト、保守できるパッチのようなものです。 これらのパッチを特定の順序で縫い合わせると、関数を組み合わせて完全なプログラムを形成するのと同じように、完全なキルトを作成します。

構造化プログラミングでは、キルターがまとまりのあるデザインを作成するためにパッチのレイアウトとシーケンスを計画する方法と同様に、制御の論理的な流れに焦点を当てています。 キルターは、各パッチが他のパッチと完全に適合し、明確で整理されたパターンを維持することを保証します。 同様に、構造化されたプログラマは、各関数がプログラム全体にシームレスに適合することを保証し、ループ、条件、サブルーチンを使用して、明確で論理的な制御フローを維持します。

このキルティングメタファーは、構造化プログラミングのモジュール性を強調しており、各関数 (またはパッチ) を必要に応じて再利用して再配置できます。 キルターがキルト全体を中断することなく個々のパッチを交換または変更できるのと同様に、プログラマはプログラム全体に影響を与えることなく個々の機能を更新または調整できます。 このモジュール性により、構造化プログラミングは、明確で保守可能で再利用可能なコードを作成するための効果的なアプローチになります。 ただし、プログラムのサイズと複雑さが増すにつれて、関数間の相互作用の管理がより困難になる可能性があります。 パッチが多すぎるキルトが扱いにくく、管理が困難になるのと同様に、多くの機能や手順を備えた構造化されたプログラムは煩雑になり、保守が困難になる可能性があります。 パッチ (関数) の数が増えるにつれて、それらがどのように一緒にフィットし、どのように相互作用するかを追跡することがより困難になります。 これにより、コードの重複、デバッグの困難、凝集の欠如などの問題が発生します。 大規模なアプリケーションでは、構造化プログラミングの線形アプローチとトップダウン アプローチにより、相互依存関数の Web が絡み合い、コードベースの理解と変更が困難になることがあります。 この複雑さは、スケーラビリティと保守容易性を妨げる可能性があり、最終的にはソフトウェアの全体的な品質とパフォーマンスに影響を与えます。

Object-Oriented プログラミングでのクラスの使用を調べる

クラスはオブジェクト指向プログラミング (OOP) の構成要素であり、プログラム内のオブジェクトの構造と動作を定義するために使用されます。 カプセル化によって提供される利点とクラスのライフサイクルを理解することは、オブジェクト指向プログラミングのしくみを理解するのに役立ちます。

カプセル化

カプセル化は、オブジェクト指向プログラミング (OOP) の基本原則の 1 つです。 これは、データを操作するデータ (フィールド) とメソッド (動作) を 1 つの単位 (通常はクラス) にバンドルすることを指します。 カプセル化では、オブジェクトのコンポーネントの一部への直接アクセスが制限されるため、データが誤って変更されるのを防ぐことができます。

カプセル化には、次の利点があります。

データの非表示: カプセル化を使用すると、オブジェクトの内部状態を外部から非表示にすることができます。 つまり、オブジェクトを使用する外部コードに影響を与えることなく、オブジェクトの内部表現を変更できます。 たとえば、プライベート フィールドを使用し、パブリック ゲッターメソッドとセッターメソッドを提供することで、データのアクセス方法と変更方法を制御できます。

保守容易性の向上: カプセル化により、コードの保守と変更が容易になります。 クラスの内部実装に対する変更は、パブリック インターフェイスが変わらない限り、クラスを使用するコードには影響しません。 この問題の分離により、開発者は意図しない副作用を気にすることなく、コードの特定の部分に集中できます。

柔軟性の向上: カプセル化により、より柔軟でモジュール式のコードが可能になります。 明確なインターフェイスを定義することで、他の部分に影響を与えることなく、コードの一部を簡単に置き換えたり更新したりできます。 このモジュール性により、コードを再利用し、よりシンプルなコンポーネントから複雑なシステムを構築しやすくなります。

セキュリティ強化: カプセル化は、承認されていないアクセスと変更を防ぐことで、オブジェクトのデータの整合性を保護するのに役立ちます。 メソッドを使用してデータへのアクセスを制御することで、データの使用方法に関する規則と制約を適用できます。 この強制は、バグを防ぎ、オブジェクトが有効な状態のままであることを確認するのに役立ちます。

抽象化: カプセル化では、オブジェクトの必要な詳細のみを外部に公開することで、抽象化の概念がサポートされます。 これにより、インターフェイスが簡略化され、オブジェクトの理解と使用が容易になります。 オブジェクトのユーザーは内部実装を知る必要はありません。これにより、コードの複雑さが軽減され、読みやすさが向上します。

手記

カプセル化とは、クラスのユーザーが必要としないデータ メンバーを非表示にすることです。 データ メンバーは、private アクセサー キーワードを使用してカプセル化または非表示になります。 非表示フィールド変数へのアクセスは、プロパティとメソッドを使用して制御されます。 非表示のデータ メンバーには直接アクセスできません。


public class Person
{
    // Private fields
    private string firstName;
    private string lastName;
    private int age;

    // Public properties with getters and setters
    public string FirstName
    {
        get { return firstName; }
        set { firstName = value; }
    }

    public string LastName
    {
        get { return lastName; }
        set { lastName = value; }
    }

    public int Age
    {
        get { return age; }
        set
        {
            if (value >= 0)
            {
                age = value;
            }
            else
            {
                throw new ArgumentException("Age can't be negative");
            }
        }
    }

    // Public method
    public void Introduce()
    {
        Console.WriteLine($"Hi, I'm {FirstName} {LastName}, and I'm {Age} years old.");
    }
}

この例では、次の操作を行います。

  • フィールド firstNamelastName、および ageprivate。つまり、クラスの外部から直接アクセスすることはできません。
  • パブリック プロパティ FirstNameLastName、および Age は、プライベート フィールドへの制御されたアクセスを提供します。
  • Age プロパティには、有効期間を負の値に設定できないようにするための検証ロジックが含まれています。
  • Introduce メソッドは、内部実装の詳細を公開することなく、オブジェクトのデータと対話する方法を提供します。

クラスのライフサイクル

C# アプリケーションでは、クラスのライフサイクルには、定義から最終的な破棄までの複数のステージが含まれます。 クラスのライフサイクルには、次の手順が含まれます。

  1. クラス定義: クラスとそのメンバーを定義します。
  2. コンパイル: クラスを IL コードにコンパイルします。
  3. 読み込み: アセンブリをメモリに読み込みます。
  4. インスタンス化: クラスのインスタンスを作成します。
  5. 初期化: オブジェクトのフィールドとプロパティを初期化します。
  6. 使用法: アプリケーションでオブジェクトを使用します。
  7. ガベージ コレクション: 不要になったときにオブジェクトのメモリを再利用します。
  8. 破棄: クリーンアップ ロジックを実行し、メモリを解放します。

クラスのライフサイクルの各ステップの説明として含まれる例を次に示します。

  1. クラス定義

    定義: クラスは、プロパティ、メソッド、およびその他のメンバーを使用してソース コードで定義されます。

    例えば:

    
    public class Person
    {
        // auto-implemented properties for name and age
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public int Age { get; set; }
    
        // method to introduce the person
        public void Introduce()
        {
            Console.WriteLine($"Hi, I'm {FirstName} {LastName}, and I'm {Age} years old.");
        }
    }
    
    
  2. 編纂

    コンパイル: ソース コードは、C# コンパイラによって中間言語 (IL) にコンパイルされます。 IL コードはアセンブリ (DLL または EXE ファイル) に格納されます。

    たとえば、Person クラスは IL コードにコンパイルされ、アセンブリに含まれます。

  3. 積載

    読み込み: アプリケーションを実行すると、共通言語ランタイム (CLR) によってアセンブリがメモリに読み込まれます。

    たとえば、Person クラスを含むアセンブリは、CLR によってメモリに読み込まれます。

  4. インスタンス

    インスタンス化: クラスのインスタンスは、new キーワードを使用して作成されます。 クラスのコンストラクターは、オブジェクトを初期化するために呼び出されます。

    例えば:

    
    Person person1 = new Person { FirstName = "Tim", LastName = "Shao", Age = 25 };
    
    
  5. 初期化

    初期化: コンストラクターは、オブジェクトのフィールドとプロパティを初期化します。 コンストラクターで定義されているすべての初期化ロジックが実行されます。

    例: Person オブジェクト person1 は、FirstNameLastName、および Ageの指定された値で初期化されます。

  6. 使い

    使用法: オブジェクトはアプリケーションで使用されます。 オブジェクトのメソッドとプロパティは、必要に応じてアクセスおよび変更されます。

    例えば:

    
    person1.Introduce();
    
    
  7. ガベージ コレクション

    ガベージ コレクション: オブジェクトが不要になり、オブジェクトへの参照がない場合、ガベージ コレクター (GC) はオブジェクトによって使用されるメモリを再利用します。 デストラクター (ファイナライザー) は、定義されている場合に呼び出されます。

    例: person1 がコード内のどこにも参照されなくなった場合、GC は最終的にそのメモリを再利用します。

  8. 隠滅

    破棄: オブジェクトのメモリが解放され、デストラクター (指定されている場合はファイナライザー) で定義されているクリーンアップ ロジックが実行されます。

    例: Personperson1 オブジェクトが破棄され、そのメモリが GC によって再利用されます。