C#のカプセル化:アクセス修飾子でコードを保護し設計を改善
カプセル化とは、「1つ以上の項目を物理的または論理的なパッケージ内に含めるプロセス」と定義されます。オブジェクト指向プログラミングにおいて、カプセル化は実装の詳細へのアクセスを防止します。
抽象化とカプセル化は、オブジェクト指向プログラミングにおける関連する機能です。抽象化が関連情報を可視化するのに対し、カプセル化はプログラマーが望むレベルの抽象化を実装することを可能にします。
カプセル化はアクセス修飾子を使用して実装されます。アクセス修飾子は、クラスメンバーのスコープと可視性を定義します。C#は以下のアクセス修飾子をサポートしています。
- Public(パブリック)
- Private(プライベート)
- Protected(プロテクテッド)
- Internal(インターナル)
- Protected Internal(プロテクテッド インターナル)
Public アクセス修飾子
Publicアクセス修飾子を使用すると、クラスはそのメンバ変数とメンバ関数を他の関数やオブジェクトに公開できます。パブリックメンバーはクラスの外部からアクセス可能です。
Publicの例
using System;
namespace RectangleApplication {
class Rectangle {
// メンバ変数
public double length;
public double width;
public double GetArea() {
return length * width;
}
public void Display() {
Console.WriteLine("Length: {0}", length);
Console.WriteLine("Width: {0}", width);
Console.WriteLine("Area: {0}", GetArea());
}
}
class ExecuteRectangle {
static void Main(string[] args) {
Rectangle r = new Rectangle();
r.length = 4.5;
r.width = 3.5;
r.Display();
Console.ReadLine();
}
}
}
実行結果:
Length: 4.5
Width: 3.5
Area: 15.75
この例では、メンバ変数lengthとwidthがpublicで宣言されているため、Main()関数からRectangleクラスのインスタンスrを使用してアクセスできます。
Private アクセス修飾子
Privateアクセス修飾子を使用すると、クラスはそのメンバ変数とメンバ関数を他の関数やオブジェクトから隠蔽できます。同じクラスの関数のみがプライベートメンバーにアクセスできます。クラスのインスタンスであっても、プライベートメンバーにはアクセスできません。
Privateの例
using System;
namespace RectangleApplication {
class Rectangle {
// メンバ変数
private double length;
private double width;
public void AcceptDetails() {
Console.WriteLine("Enter Length: ");
length = Convert.ToDouble(Console.ReadLine());
Console.WriteLine("Enter Width: ");
width = Convert.ToDouble(Console.ReadLine());
}
public double GetArea() {
return length * width;
}
public void Display() {
Console.WriteLine("Length: {0}", length);
Console.WriteLine("Width: {0}", width);
Console.WriteLine("Area: {0}", GetArea());
}
}
class ExecuteRectangle {
static void Main(string[] args) {
Rectangle r = new Rectangle();
r.AcceptDetails();
r.Display();
Console.ReadLine();
}
}
}
実行結果:
Enter Length: 4.4
Enter Width: 3.3
Length: 4.4
Width: 3.3
Area: 14.52
この例では、メンバ変数がprivateなのでMain()から直接アクセスできません。パブリックなメソッドAcceptDetails()とDisplay()を通じて間接的にアクセスします。
Protected アクセス修飾子
Protectedアクセス修飾子を使用すると、子クラスが基底クラスのメンバ変数とメンバ関数にアクセスできるようになります。これにより継承の実装が容易になります。詳細は継承の章で説明します。
Internal アクセス修飾子
Internalアクセス修飾子を使用すると、クラスはそのメンバ変数とメンバ関数を、現在のアセンブリ内の他の関数やオブジェクトに公開できます。つまり、internalメンバーは、そのメンバーが定義されているアプリケーション内で定義されている任意のクラスやメソッドからアクセス可能です。
Internalの例
using System;
namespace RectangleApplication {
class Rectangle {
// メンバ変数
internal double length;
internal double width;
double GetArea() { // アクセス修飾子なし = private
return length * width;
}
public void Display() {
Console.WriteLine("Length: {0}", length);
Console.WriteLine("Width: {0}", width);
Console.WriteLine("Area: {0}", GetArea());
}
}
class ExecuteRectangle {
static void Main(string[] args) {
Rectangle r = new Rectangle();
r.length = 4.5;
r.width = 3.5;
r.Display();
Console.ReadLine();
}
}
}
実行結果:
Length: 4.5
Width: 3.5
Area: 15.75
注目すべき点:メンバ関数GetArea()にはアクセス修飾子が指定されていません。クラスメンバーにアクセス修飾子を指定しない場合のデフォルトはprivateです。
Protected Internal アクセス修飾子
Protected internalアクセス修飾子を使用すると、同じアプリケーション内の子クラスを除き、他のクラスのオブジェクトや関数からメンバ変数とメンバ関数を隠蔽できます。これも継承の実装時に使用されます。
アクセス修飾子のアクセシビリティまとめ
| 修飾子 | 同一クラス | 派生クラス(同一アセンブリ) | 非派生クラス(同一アセンブリ) | 派生クラス(別アセンブリ) | 非派生クラス(別アセンブリ) |
|---|---|---|---|---|---|
| public | ✓ | ✓ | ✓ | ✓ | ✓ |
| protected internal | ✓ | ✓ | ✓ | ✓ | ✗ |
| internal | ✓ | ✓ | ✓ | ✗ | ✗ |
| protected | ✓ | ✓ | ✗ | ✓ | ✗ |
| private | ✓ | ✗ | ✗ | ✗ | ✗ |
ベストプラクティス
- フィールド(メンバ変数)は原則として
privateにし、プロパティで公開する - 外部に公開する必要のあるメソッドのみ
publicにする - 継承でオーバーライドを許可するメソッドは
protectedまたはpublicにする - アセンブリ内でのみ共有する機能には
internalを使用する - 「最小権限の原則」に従い、必要最小限のアクセス権のみを与える
C言語
- C# クラスとオブジェクト:堅牢な OOP の基礎
- C# アクセス修飾子を理解する:public、private、protected、internal など
- C# static キーワード:静的変数、メソッド、クラスをマスターする
- C# 抽象クラスと抽象メソッドをマスターする:実践ガイド
- C# 入れ子クラスを理解する:定義、使用法、継承
- C# 部分クラスと部分メソッドを理解する
- C# sealed クラスとメソッドをマスターする:使用判断、実例、コードの安全性とパフォーマンス向上
- C++ポリモーフィズム完全理解:仮想関数と純粋仮想関数
- C++データ抽象化完全マスター:インターフェースと実装の分離
- C++データカプセル化:コードを守る仕組みと実装例
- Javaカプセル化完全解説: データ隠蔽・ゲッター/セッター・アクセス制御の実践