クラス -アクセス制限-

ホームC#プログラミング応用講義 > アクセス制限

目次

セキュリティ

初心者・入門者にとって難関なのが「アクセス制限」です。なぜこんな面倒なことをと思ってしまいま す。
しかし、アクセス制限の機能をうまく利用すれば大変いいプログラムを書くことができます。

入門講座ではほとんどやっていませんので詳しく説明していきます。この項目ではアクセス制限についてその価値を説明します。

アクセス

オブジェクトはそれ単体で独立しているものの、外部からまったくアクセスしないわけではありません。オブジェクトの中の変数やメソッドにアクセスしなけれ ば、動作をしないからです。

しかし、その際図のように「★」であらわした変数やメソッド(いわゆるメンバ)に対して自由自在にアクセスできてしまうと、オブジェクトの独立性が失われ るばかりか、大きな弊害が出てきます。

その最も大きなものは「名前の衝突」です。上の図のオブジェクトの中で A というメンバを宣言したとすると、外部に A というメンバを宣言することはできません。(ローカル変数はここでは無視します)
そのため A という名前をつけたくても別の名前を使わざるを得ません。

これは頻繁に発生します。例えば前回の面積を求めるプログラムなら「width」「height」などの変数名は長方形でも三角形でも利用したいのです が、名前の衝突が発生するとどちらかを変えなければなりません。このようなものを「名前の衝突」と呼びます。

さらに、オブジェクトには外部からはいじられたくないものも多く存在します。外部からのアクセスを許可したいものもあれば許可したくない、自分のオブジェ クト内だけで処理したいものもあるのです。このような際に「アクセス制限」の機能があればそれらを区別することができるのです。

アクセス2

外部からアクセスできるものもあればできないものもある。これが理想のあり方です。
この画像では右・左・真ん中の3つのメンバは外部からのアクセスを許可されておらず、残りの3つはアクセスが可能です。

ただし、これらすべてのメンバはオブジェクトの中からは自由にアクセスできます。アクセスで きなければ使い物になりません。
アクセス制限というのは「自分」と「外部」との間のアクセスに関する許可ということになります

(C# におけるアクセス制限はこの「許可する」「許可しない」のほかにも複雑な働きをする「protected」などがありますが、これはクラスの継承が必須な ので後にやることにします。)

public/private

つい最近小泉首相の靖国神社参拝に関する判決があり、そこでは「公用」「私用」という ことが最も重要な争点となりま した。
上で述べた「許可する」「許可しない」は「公」「私」という言葉で区別されます。

公 として指定されたものはどこでも通用しますが 私 として指定されたものは自分の家(オブジェクト)の中でしか通用しません。
公と私の区別を指定するキーワードがそれぞれ
public / private
です。パブリックプライベートは それぞれ日本語になっていますからわかりやすいでしょう。
using System;

class Class1
{
// Main()は public
public static void Main(string[] args)
{
// なにも指定しなければ private
Class2 cls2 = new Class2();
cls2.a = "山田奈緒子"; // アクセス可
/*
cls2.b = "上田次郎"; // アクセス不可
*/
cls2.show(); // アクセス可
}
}

class Class2
{
public string a = "空っぽ"; // これは '公'
private string b = "空っぽ"; // これは '私'

// これは '公'
public void show()
{
Console.WriteLine("a=={0},b=={1}",a,b);
}
}
Class1 から Class2 のメンバにアクセスする際に、Class2 のメンバ a は public 指定であるのに対して、b は private 指定です。
そのため、cls2.b はアクセス不可となってしまうので、このプログラムではコメントをかけています。(上田次郎のところ)

クラスにおいて何もアクセス修飾子が指定されなかった場合、private として扱われます
ここでは Class1 内で Class2 のオブジェクトを生成する際にアクセス修飾子をつけていませんが、これは private を指定しているのと同じように扱われます。

アクセス修飾子を指定できるのは変数だけではありません。メソッドももちろん指定することができます。
ここでは show() メソッドは public 指定であるため、Class1 からもアクセスすることが可能になるわけです。

ちなみに、Main() メソッドに関しては public でも private でもかまわないのですが、VisualStudio.NET において public が採用されていることもあり、public を好むプログラマが多いようです。そのため、通常は public を指定指定しておけばいいでしょう。

何でもかんでも public にしてしまう場合をよく見ます。私の友人の一人は public 地獄に陥っているようです。
しかし、public を指定するのは外部からアクセスすべきものだけであって、内部からアクセスするものは private(デフォルト) 指定すべきです。

上の b に値を代入したい場合はどうしたらいいのでしょうか? 必ずしも b を public にする必要はありません。
コンストラクタ・メソッドの引数に指定すれば private なメンバにも実質的に代入できます。
using System;

class Class1
{
// Main()は public
public static void Main(string[] args)
{
// なにも指定しなければ private
Class2 cls2 = new Class2();
cls2.a = "山田奈緒子"; // アクセス可
cls2.show("上田次郎"); // アクセス可
}
}

class Class2
{
public string a = "空っぽ"; // これは '公'
private string b = "空っぽ"; // これは '私'

public void show(string str)
{
Console.WriteLine("a=={0},b=={1}",a,b);
b = str;
Console.WriteLine("a=={0},b=={1}",a,b);
}
}
前回コンストラクタに渡したので、今回は show() メソッドに渡しています。
こうすることで直接ではないものの private に変数を代入できます。(ただし、このように利用するのは Class2 の内部処理だけです。)

public/private をうまく使い分けることによって、セキュリティを高めること ができます。むやみやたらに public を作ってしまっては前に述べた名前の衝突などが発生しますので、private を基準に考えて、外部からのアクセスを許可する場合には特例として public を指定すると考えておきましょう。
(かなり脅かすようなことを書いたかもしれませんが、慣れてくるので余り神経質になる必要はありません。頭の片隅においておけばいいでしょう)

[ ステップアップC# ] [ C#プログラミング応用講義 ]