Day 35 のゴールと全体像
Day 35 のテーマは アクセス修飾子 です。 いよいよ「クラスの中身をどこまで見せるか・隠すか」という、 オブジェクト指向らしい話に入っていきます。
学ぶキーワードは次の 4 つです。
publicprivateprotectedinternal
ざっくり言うと、
「このメンバーは、誰から触っていいのか?」
を決めるための仕組みだと思って読んでいただけると、イメージしやすいと思います。
アクセス修飾子とは何か
「見せる/隠す」をコードで決めるためのラベル
アクセス修飾子は、
クラスやメンバー(フィールド・プロパティ・メソッドなど)に対して、 どこからアクセスできるかを指定するためのキーワード
です。
例えば、
public class Person
{
public string Name; // どこからでも見える
private int age; // クラスの中からしか見えない
public void Introduce()
{
Console.WriteLine($"こんにちは、{Name} です。年齢は {age} 歳です。");
}
}
C#このように、
- 「外から触ってほしいもの」には
public - 「クラスの中だけで使いたいもの」には
private
というように、 意図に合わせて「公開範囲」を決めるのがアクセス修飾子の役割です。
public:みんなから見える窓口
「どこからでもアクセスしていいよ」という宣言
public は、
「どこからでもアクセスしていい」
という意味のアクセス修飾子です。
クラスの外から使ってほしいメソッドやプロパティには、 基本的に public を付けます。
public class Person
{
// 外から名前を設定・取得してほしいので public
public string Name { get; set; }
// 外から自己紹介してほしいので public
public void Introduce()
{
Console.WriteLine($"こんにちは、{Name} です。");
}
}
class Program
{
static void Main(string[] args)
{
Person p = new Person();
// public なメンバーには、クラスの外からアクセスできます
p.Name = "太郎";
p.Introduce();
Console.ReadLine();
}
}
C#重要ポイント:
publicは「外部に公開するインターフェース」を作るためのキーワードです。- 何でもかんでも
publicにすると、クラスの中身が丸見えになり、 後で変更しづらくなるので、必要なものだけを公開する意識が大事です。
private:クラスの中だけの秘密
「このクラスの中だけで使う」ための修飾子
private は、
「そのクラスの中からしかアクセスできない」
という意味のアクセス修飾子です。
フィールドや、内部的な補助メソッドなど、 「外から直接触ってほしくないもの」に使います。
public class Person
{
// 実際の年齢データは private フィールドに
private int age;
// 外からはプロパティ経由でアクセスさせる
public int Age
{
get { return age; }
set
{
if (value < 0)
{
age = 0;
}
else
{
age = value;
}
}
}
public void Introduce()
{
Console.WriteLine($"こんにちは、年齢は {Age} 歳です。");
}
}
C#ここでは、
ageフィールドはprivateなので、Personクラスの外からは直接触れません- 外からは
Ageプロパティを通して、年齢を読み書きします
という構造になっています。
重要ポイント:
privateは「クラスの内側の事情」を隠すためのキーワードです。- 外から直接触らせないことで、 「中身の実装を変えても、外側の使い方は変えなくて済む」 というメリットが生まれます。
protected:継承したクラスからは見える
「自分と子どもだけが知っている情報」
protected は、
「そのクラス自身と、そのクラスを継承したクラスからアクセスできる」
という意味のアクセス修飾子です。
少し先の話になりますが、 継承(class Student : Person のような形)を使うときに登場します。
イメージとしては、
「親クラスと子クラスの間だけで共有したい情報」
に使うラベルです。
簡単な例を見てみましょう。
public class Animal
{
// 子クラスにも見せたいので protected
protected string Name;
public Animal(string name)
{
Name = name;
}
}
public class Dog : Animal
{
public Dog(string name) : base(name)
{
}
public void Bark()
{
// Dog は Animal を継承しているので、protected な Name にアクセスできます
Console.WriteLine($"{Name} が吠えました。ワンワン!");
}
}
class Program
{
static void Main(string[] args)
{
Dog d = new Dog("ポチ");
d.Bark();
Console.ReadLine();
}
}
C#ここでのポイントは、
Nameはprotectedなので、AnimalとDogの中からは見える- しかし、
Programなど「外のクラス」からは見えない
というところです。
重要ポイント:
protectedは「継承関係の中だけで共有したいもの」に使います。- まだ継承を本格的に学んでいない段階では、 「親子だけの秘密を作るキーワード」と覚えておくくらいで十分です。
internal:同じアセンブリの中だけで公開
「同じプロジェクトの中だけで使える」
internal は、
「同じアセンブリ(ざっくり言うと同じプロジェクト)の中からだけアクセスできる」
という意味のアクセス修飾子です。
コンソールアプリのような単一プロジェクトでは、 internal と public の違いはあまり意識しなくても困りませんが、 ライブラリを作ったり、複数プロジェクトに分けて開発するときに効いてきます。
簡単なイメージとしては、
「このプロジェクトの中では公開したいけれど、 外のプロジェクトからは隠しておきたい」
というときに使うラベルです。
例として、クラスに internal を付けるとこうなります。
internal class InternalHelper
{
public void DoSomething()
{
Console.WriteLine("プロジェクト内だけで使うヘルパーです。");
}
}
C#このクラスは、
- 同じプロジェクトの中からは普通に使える
- 別のプロジェクトからは見えない
という扱いになります。
重要ポイント:
internalは「プロジェクトの外には出したくないけれど、中では使いたいもの」に使います。- 初学者の段階では、 「
publicは完全に外部公開、internalはプロジェクト内限定公開」 くらいのイメージで十分です。
4 つのアクセス修飾子をまとめてイメージする
ざっくりイメージ図
感覚的には、次のような「公開範囲の広さ」で覚えると分かりやすいです。
public- いちばん広い
- どこからでも見える
internal- 同じプロジェクトの中からだけ見える
protected- 自分と子クラスからだけ見える
private- いちばん狭い
- 自分のクラスの中だけで見える
実務では、
- フィールドは基本
private - 外から使ってほしいメソッドやプロパティは
public - 継承を使うときに
protected - ライブラリや大きなプロジェクトで
internal
という使い分けがよく登場します。
Day 35 用の練習テンプレート
最後に、アクセス修飾子の感覚をつかむための、 シンプルな練習用クラスを紹介します。
アクセス修飾子をまとめて使った例
using System;
public class Sample
{
// 外からは見えないフィールド
private int privateValue = 10;
// 継承したクラスからは見えるフィールド
protected int protectedValue = 20;
// プロジェクト内から見えるフィールド
internal int internalValue = 30;
// どこからでも見えるプロパティ
public int PublicValue { get; set; } = 40;
// 外からはこのメソッドだけを使ってもらう
public void ShowValues()
{
Console.WriteLine($"privateValue: {privateValue}");
Console.WriteLine($"protectedValue: {protectedValue}");
Console.WriteLine($"internalValue: {internalValue}");
Console.WriteLine($"PublicValue: {PublicValue}");
}
// クラスの中だけで使う補助メソッド
private void SecretMethod()
{
Console.WriteLine("これはクラスの中だけで呼ばれる秘密のメソッドです。");
}
public void CallSecret()
{
// 外からは SecretMethod を直接呼べないが、
// このメソッド経由なら呼べるようにしている
SecretMethod();
}
}
class Program
{
static void Main(string[] args)
{
Sample s = new Sample();
// public なメンバーにはアクセス可能
s.PublicValue = 100;
s.ShowValues();
s.CallSecret();
// s.privateValue; // コンパイルエラー(private のため)
// s.protectedValue; // コンパイルエラー(protected のため)
// s.internalValue; // 同じプロジェクトならアクセス可能
Console.ReadLine();
}
}
C#このテンプレートを眺めながら、
- 「どこから見えて、どこから見えないのか」
- 「外から触ってほしいものと、隠したいものの違い」
を意識してみると、アクセス修飾子の役割がぐっとクリアになります。
Day 35 のまとめ
Day 35 では、
public:どこからでもアクセスできるprivate:そのクラスの中だけからアクセスできるprotected:そのクラスと、そのクラスを継承したクラスからアクセスできるinternal:同じプロジェクト(アセンブリ)の中からだけアクセスできる
という 4 つのアクセス修飾子を通して、 「クラスの中身をどこまで見せるか・隠すか」 という視点を学びました。
オブジェクト指向の世界では、
「何を隠して、何を見せるか」
をきちんと設計することが、 安全で変更に強いコードにつながっていきます。
ぜひ、
- 自分でクラスを 1 つ作って、フィールドは
private、外向きの窓口はpublicにしてみる - 「これは外から触らせたくないな」と思うものに、意識的に
privateを付けてみる - 継承を学んだときに、「親子だけの共有」に
protectedを使ってみる
といった練習を通して、 アクセス修飾子を 「ただのキーワード」ではなく、 クラスの設計を支える大事な道具として、少しずつ自分の感覚に馴染ませていってください。
