ここではC#のアクセス修飾子について学びます。これもクラスの延長線の話になります。
最低でもクラスと継承の知識が必要なので、忘れてしまった人は以下で復習しましょう。
ここではC#のクラスについて学びます。クラスはC#において最も大切な機能だと思ってます。それもあって最低限の内容を書いたつもりが、何かめっちゃ長くなりました。疲れたら数回に分けて読んでください。 クラス(class) クラスとは特定の機能を1つにまとめたものです。正直、説明が難しいのでコードを使って話します。最初に以下の記述方法とサンプルコードを見てください。これは車という機能をクラス化したコードです。 // クラス public class Car { ...
ここではC#の継承について学びます。これはクラスの延長線の話になりますが少し難しいです。まずはクラスの基礎知識が必要なので、忘れてしまった人は以下で復習しましょう。 継承(inheritance) 継承とは、あるクラスを元に新しいクラスを定義することです。こうすることで新しく定義したクラスは元になったクラスの全ての機能を有することができます。 簡単に言えば親子関係です。親(A)を元に子(B)を定義することができます。人間なら全ての特性を引き継ぐことはありませんが、この世...
アクセス修飾子(Access Modifiers)
アクセス修飾子とは、クラス、メソッド、プロパティ、フィールド等へのアクセス範囲を制限するために使います。
既に解説したprivateとpublicを含めると、全部で5種類(public, protected, internal, private, file)あります。
さらに複数のアクセス修飾子の組み合わせが可能で、実際には7つのアクセスレベルを指定できます。
以下は構文の例です。
public
最もアクセス制限が緩いです。と言うか、アクセス制限がされません。
つまり、publicを記述すると外部からのアクセスが無条件で許可されます。
namespace Sample
{
public class Base
{
// publicフィールド
public int value = 100;
}
internal class Program
{
static void Main(string[] args)
{
var b = new Base();
// 無条件にアクセスが可能
System.Console.WriteLine(b.value);
b.value *= 2;
System.Console.WriteLine(b.value);
}
}
}
publicはアクセス制限がないので、基本的に外部からクラスを操作するためのメソッドやプロパティにしか付けません。
特にフィールドに付けることはなく、仮に指定が必要になってる場合は設計の問題を疑ったほうがいいです。
さっきのサンプルコードは非常に悪い例です。こうすると外部から勝手に値を変更できるのでバグの元になります。
protected
後に説明するprivateより少し緩い版です。指定するとクラス自身か継承したクラスしかアクセスできません。
ちょっと例が難しいのですが、外部公開までは必要ないけど、自分を継承したクラスはアクセス可能にしたい場合に使います。
namespace Sample
{
public class Base
{
// protectedフィールド
protected int value = 100;
}
public class Derived : Base
{
public int GetValue()
{
// 継承したクラスはアクセス可能
return value;
}
}
internal class Program
{
static void Main(string[] args)
{
var d = new Derived();
System.Console.WriteLine(d.GetValue());
// 外部はアクセス不可能
//System.Console.WriteLine(d.value);
}
}
}
クラスを継承しない限りはprivateと同義です。
internal
アクセスを同一アセンブリに限定します。この時点では分かりづらいと思いますが、同一アセンブリとは同じプロジェクトを意味します。
以前にプログラムはプロジェクト単位でも分割できると話しましたが、その時に別プロジェクトからのアクセスが禁止になります。
namespace Sample
{
// 別プロジェクトからはアクセス不可能
internal class InternalClass
{
}
// 別プロジェクトでもアクセス可能
public class PublicClass
{
}
}
同プロジェクトから見ればpublicを指定するのと同義です。
private
アクセスを自分自身に限定します。後述するfileが特殊なため、これが実質的に最も厳しいアクセス制限となります。
基本的な考え方として、クラス内のフィールドは全てprivateにします。それ以外だと内部でしか利用しないメソッドやプロパティに付けます。
protectedとの違いは継承先からのアクセス制限です。privateは継承先も含め、自身以外はアクセス禁止になります。
namespace Sample
{
public class Base
{
// privateフィールド
private int v1 = 100;
// protectedフィールド
protected int v2 = 300;
}
public class Derived : Base
{
public void Display()
{
// アクセス不可能
//System.Console.WriteLine(v1);
// アクセス可能
System.Console.WriteLine(v2);
}
}
internal class Program
{
static void Main(string[] args)
{
var d = new Derived();
d.Display();
}
}
}
file
これはアクセスを現在のソースコードに限定します。つまり別のファイルからのアクセスを禁止します。
別ファイルでも同名の名前空間の内部は同じスコープになるため、そこで名前が被るような場合にfileを使うことで被りが許容されます。
namespace Sample
{
// ファイル内からのみアクセス可能
file class Base
{
public void Display()
{
System.Console.WriteLine("りさ");
}
}
internal class Program
{
static void Main(string[] args)
{
var b = new Base();
b.Display();
}
}
}
これまで当然のように書いてますが、本来は1ファイルに1クラスが原則です。例のように1つのファイルに全てを記述するパターンは少ないです。
それでも1ファイルに複数のクラス、例えば補佐するサブクラス等を書きたい場合があり、そういうパターンで利用すると便利だったりします。
そもそも上位の名前空間で名前被りは設計的にどうなのって意見もあるので賛否両論。
アクセス修飾子の組み合わせ
先程のアクセス修飾子を組み合わせて使えるパターンです。と言っても無理に覚える必要はありません。
正直、先程のfileを除く4つ(public, protected, internal, private)があれば基本的に困りません。
知識勢でも目指さない限りは単体4個で十分です。
protected internal
これはprotectedまたはinternalです。通常のprotectedに加えて別アセンブリからもアクセスできます。
ただ、正直なところ僕はこれの使い道が分かりません。と言うのもinternalが付くと同一アセンブリで全許可になります。
要はアクセス範囲が広すぎると思うんですよね。仮に同一アセンブリを1人で開発した場合でも全許可は雑。
private protected
パターンが無いからこの組み合わせを採用したんでしょうね。ただただ分かりづらくなってます。
これは実質的にprotectedかつinternalです。つまり、さっきの話のアクセス範囲が広すぎ問題を解決してくれます。
いっそprotected internalの機能を作り替えたほう幸せだったのでは。
記述可能な項目
先程のアクセス修飾子ですが、何でもかんでも記述できる訳ではありません。
大雑把に分類すると、記述対象がトップレベルか否かで記述可能なアクセス修飾子が変わります。
トップレベルの場合
これはnamespace配下に記述したクラス宣言など、つまりは最上位に位置する場合を意味します。
この場合に記述できるのはinternalとpublicの2種類のみです。ちなみにDefault値はinternalになります。
あまり難しく考えないで欲しいのですが、これは当たり前のことで、最上位のクラスに他のアクセス修飾子を付けると誰もアクセスできません。
つまりは同じアセンブリだろうと、誰もアクセスできないゴミみたいなクラスが誕生します。これでは意味がないですよね。
namespace Sample
{
// 誰もアクセスできないからビルドエラー
private class Base
{
}
}
メンバの場合
トップレベルでない場合、つまりは何らかのメンバになってる場合です。
例えばクラスに含まれるフィールドやメソッド、クラスのクラスとかもメンバって言います。
この場合は先程説明した数々のアクセス修飾子を記述できます。なお、Default値は大体privateになります(たぶん)。
曖昧ですね。
個人的にはアクセス修飾子は省略せず記述したほうが良いです。と言うか、僕自身が省略しないのでDefault値を知りません。
あとがき
最初はpublic, protected, privateの3つを覚えれば十分だと思う。正直、internalも人それぞれな印象。
少なくとも何でもかんでもpublicを指定するのは辞めましょう。インテリセンス利用時の見栄えも悪くなります。
◆ C#に関する学習コンテンツ
この記事は参考になりましたか?
コメント