アクセス修飾子
CoddyのC#ジャーニー「オブジェクト指向プログラミング」セクションの一部 — レッスン 31/70。
アクセス修飾子は、クラスのメンバーを誰が参照し、使用できるかを制御します。これらは、OOP(オブジェクト指向プログラミング)の核となる原則の1つである「カプセル化」の基礎となります。アクセスを制限することで、データを保護し、コード内に明確な境界線を作成することができます。
C#は、主に4つのアクセス修飾子を提供します:
public class BankAccount
{
public string AccountHolder; // どこからでもアクセス可能
private decimal balance; // このクラス内からのみ
protected string accountType; // このクラスおよび派生クラスから
internal int branchCode; // 同じアセンブリ内から
}public メンバは、どのコードからでもアクセス可能です。
private メンバーは、同じクラス内からのみアクセスできます。これは最も制限が厳しく、クラスメンバーのデフォルトの設定です。
protected は、クラス自身およびそれを継承するすべてのクラスからのアクセスを許可します。
internal は、同じアセンブリ(プロジェクト)内のコードへのアクセスを制限します。
修飾子が指定されていない場合、クラスメンバーはデフォルトで private になります:
class Example
{
int secret; // デフォルトでprivate
}適切なアクセスレベルを選択することは、必要なものだけを公開することです。まずは private から始め、明確な理由がある場合にのみ可視性を高めるようにしてください。これにより、後で変更する可能性のある実装の詳細に他のコードが依存するのを防ぐことができます。
チャレンジ
簡単アクセス修飾子がどのように機密データを保護し、必要な情報のみを公開するかを実証する、安全なユーザープロファイルシステムを構築しましょう。アクセス権限に基づいて、情報の各要素が異なる可視性レベルを持つクラスを作成します。
コードは以下の3つのファイルに分けて構成します:
UserProfile.cs:Security名前空間内に、適切なアクセスレベルでユーザー情報を管理するUserProfileクラスを作成します。プロファイルには以下の要素を含める必要があります:publicプロパティUsername(string) - 誰でもユーザー名を確認できますprivateフィールドpassword(string) - クラス自身のみがアクセスできますprotectedフィールドemail(string) - クラスとその派生クラスがアクセスできますinternalフィールドuserId(int) - 同じアセンブリ内からアクセス可能です
"User: {Username}"を返すGetPublicInfo()というpublicメソッドを追加します。また、入力がプライベートなパスワードと一致すればtrueを、そうでなければfalseを返すValidatePassword(string input)という別のpublicメソッドを追加します。AdminProfile.cs:Security名前空間内に、UserProfileを継承するAdminProfileクラスを作成します。このクラスは、派生クラスでprotectedメンバーがどのようにアクセス可能になるかを実証します。コンストラクタは同じ4つのパラメータを受け取り、それらをベースクラスのコンストラクタに渡す必要があります。"Admin: {Username}, Email: {email}"を返すGetAdminInfo()というpublicメソッドを追加してください。ここでは保護されたemailフィールドにアクセスできることに注目してください!Program.cs: メインファイルで、入力値を使用してUserProfileとAdminProfileを作成します。利用可能なパブリックメソッドを呼び出し、(同じアセンブリ内にいるため)内部フィールドに直接アクセスすることで、アクセスレベルを実証します。各タイプのユーザーがどのような情報を明らかにできるかを示してください。
5つの入力を受け取ります:
- Username
- Password
- User ID (整数)
- 検証するパスワードの試行入力
出力を以下の形式で表示してください:
Regular User:
{GetPublicInfo() result}
Internal ID: {userId}
Password valid: {ValidatePassword result}
Admin User:
{GetAdminInfo() result}例えば、入力が alice, secret123, alice@email.com, 1001, secret123 の場合、出力は以下のようになります:
Regular User:
User: alice
Internal ID: 1001
Password valid: True
Admin User:
Admin: alice, Email: alice@email.comパスワードが完全に隠されたままであることに注目してください。検証はできますが、取得することはできません。メールアドレスは保護されているため、AdminProfile(派生クラス)のみがそれを公開できます。内部のuserIdは、同じアセンブリ内にあるため、メインファイルからアクセス可能です。これがカプセル化の仕組みです!
チートシート
アクセス修飾子は、クラスメンバーの可視性とアクセシビリティを制御し、OOPにおけるカプセル化の基礎を形成します。
C#には、主に4つのアクセス修飾子があります:
public class BankAccount
{
public string AccountHolder; // どこからでもアクセス可能
private decimal balance; // このクラス内のみ
protected string accountType; // このクラスおよび派生クラス内
internal int branchCode; // 同じアセンブリ内
}public: あらゆるコードからアクセス可能
private: 同じクラス内からのみアクセス可能(最も制限が厳しく、クラスメンバーのデフォルト)
protected: クラス自体および派生クラスからアクセス可能
internal: 同じアセンブリ(プロジェクト)内からのみアクセス可能
修飾子が指定されていない場合、クラスメンバーはデフォルトで private になります:
class Example
{
int secret; // デフォルトで private
}ベストプラクティス:外部コードが実装の詳細に依存するのを防ぐため、最初は private から始め、必要な場合にのみ可視性を高めます。
自分で試してみよう
using System;
using Security;
class Program
{
public static void Main(string[] args)
{
// 入力を読み込む
string username = Console.ReadLine();
string password = Console.ReadLine();
string email = Console.ReadLine();
int userId = Convert.ToInt32(Console.ReadLine());
string passwordAttempt = Console.ReadLine();
// TODO: 入力値を使用して UserProfile オブジェクトを作成する
// TODO: 同じ入力値を使用して AdminProfile オブジェクトを作成する
// TODO: "Regular User:" を出力する
// TODO: GetPublicInfo() の結果を出力する
// TODO: "Internal ID: " に続いて userId フィールド(同じアセンブリ内なのでアクセス可能)を出力する
// TODO: "Password valid: " に続いて ValidatePassword() の結果を出力する
// TODO: "Admin User:" を出力する
// TODO: GetAdminInfo() の結果を出力する
}
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。