C#のアクセス修飾子とUnityでの扱いを知っておくとグッド
アクセス修飾子の話はUnityでコーディングをする上でよく出てくる話です。
C#ではアクセス修飾子と呼ばれるキーワードを使って、対象のフィールドやメソッドに対してどこからアクセスできるかを決めています。
これは「アクセシビリティレベル」と呼ばれていて、アクセス修飾子単体または組み合わせて6段階のレベルを決めることができます。「アクセシビリティ」は近づきやすさ、利用しやすさといった意味の言葉で、どれだけ利用できるかのレベルを表しています。
どこからでも利用できたり、あるいはそのクラスでしか使えなかったりと、利用範囲に応じてアクセシビリティレベルを使い分けるのが鉄則。C#はオブジェクト指向のプログラミング言語なので、カプセル化や隠蔽の考え方に沿って、基本はそのクラスだけで使えるようにしたいところです。
ただし、Unityではインスペクターウィンドウから値を変更・調整できるようにすることでゲームのチューニングが容易になるので、こうした面からも適切なアクセス修飾子を選択できるようになるとグッド。
という訳でこのページではアクセス修飾子の種類を紹介し、Unityのインスペクターウィンドウで使うときにどれを選択すべきかも紹介していきます。
アクセス修飾子の種類
アクセス修飾子は
- public
- protected
- private
- internal
の4つがあります。
ざっくりと説明すると、publicはどこからでもアクセスできて、protectedは派生クラス(継承したクラス)で使えます。
privateはそのクラス内でしかアクセスできません。internalは同じアセンブリ内ならアクセスできます。
これらを単体で使う場合に加えて、組み合わせて使う「protected internal」や「private protected」もあります。こちらは名前の紹介だけにとどめますので、興味があれば調べてみてください。
internalとDLLの話
ちなみにinternalで出てきたアセンブリというのは.exeとか.dllといったアプリケーションの構成要素のことです。Unityではデフォルトだとユーザーが書いたコードはAssembly-CSharp.dllのファイルにまとまっているのでひとつのアセンブリ内でコーディングしています。dllとはDynamic Link Libraryの略で、プログラムを動かすときに使われる部品を表しています。
.dllファイルはプロジェクトフォルダの中にあるLibrary/ScriptAssembliesを見ると確認できます。アセットをインポートすると増えていたりするかもしれません。また、TextMeshProや2D Tilemap Editorなど、Unityのパッケージマネージャからインポートしたパッケージについてもdllファイルが作成されていたりします。
ユーザーが書いたコードについてもdllを分けたりできます。これによってコンパイルにかかる時間が短縮できるので、慣れてきたらこちらも検討するとグッド。この点についてはテラシュールブログさんのところで詳しく解説されているのでこちらもぜひ。
基本はprivate
コーディングを行う際は、基本的にはprivateを使います。これは他のクラスからフィールドの値を変えられるといつ値が変わったか把握するのが大変になったりするためです。
オブジェクト指向の考え方だと、オブジェクトの振る舞いはオブジェクトの中で完結して結果だけ返すような組み方が良いんですよね。
例えば上司が部下に対して、
「PC立ち上げて」
「Excel開いて」
「テストケースのファイルを開いて」
「C24のセルにこの値を入れて」
「ファイルを保存して」
「私(上司)にメールで送って」
と逐一指示していたら、ふたりの時間がもったいないですよね。仕様が変わったらまた上司の指示内容が細かく変わったりするので、上司、部下のどちらの立場も大変です。
この場合だったら、上司から
「必要なデータは渡すからテストケースにまとめた後、私にメールで送ってください」
と部下にお願いすれば部下はちゃんと作ってくれるはずです。仕様が変わったとしても、部下側で調整すればいいので、上司は完成したテストケースのファイルを受けとるだけでOKです。
こんな感じで別のオブジェクトに対して逐一指示するするのではなく、「これやって」とお願いして、「できたよー」と結果が返ってくる関係が理想的。なので、わざわざpublicにして公開せずとも内部だけで値を持っていればいいこともあります。外からわーわー言われることで値が変わって逆に効率が落ちたり意図しない結果になってしまったりするので、必要がないときにはprivateにしておきたいところです。
また、アクセスレベルを指定しない場合はprivateとして扱われます。意図せず広いアクセスレベルになっていた! なんてことがないので安心ですね。
明示的にprivateをつけるべきかは好みによるところですが、public, protected, privateと全部pで始まるので紛らわしいなーと思い、自分でコードを書くときはつけていません。一緒にやっている人が「privateつけるよ派」だったら合わせる感じです。
継承するならprotected
継承したクラスでフィールドやメソッドを使いたい場合も多々あります。そうした時はprotectedを使って継承しましょう。
スクリプトを作成したときには以下のように「MonoBehaviour」のクラスを継承しています。
なので、私たちが処理を書かなくても「gameObject」と指定すればアタッチしたゲームオブジェクトの情報を使うことができたり、あるいはGetComponentでコンポーネントへの参照を取得できたりするんです。
継承やオーバーライドについては以下の記事で紹介しているのでこちらもよかったらどうぞ。
Unityでのpublic
Unityではpublicなフィールドの扱いが特殊で、MonoBehaviourを継承したクラスについてはpublicなフィールドの値をインスペクターウィンドウから変更できます。
「インスペクターウィンドウから値を変えたい時はpublicだ!」
とたくさんのフィールドがpublicになることもありますが、publicにすることでインスペクターウィンドウだけではなく他のクラスからも値を変更できてしまう点には注意が必要です。
インスペクターウィンドウから値を変えたい、でもなるべくフィールドを公開したくない、という場合はprivateなフィールドに[SerializeField]のアトリビュート(属性)をつけることでもインスペクターウィンドウから値を変えられます。
ひとりで開発するならpublicが楽かもしれませんが、他の人と一緒に開発するならなるべくprivateのままにしておきたいところです。
この辺りはアクセシビリティレベルを意識してうまく使い分けられると安全なコードを書けると思います。
Attributeについては以下の記事で紹介しているのでよかったらこちらもご覧くださいな。
まとめ
C#でアクセシビリティレベルを表現するために使うアクセス修飾子を紹介しました。このうちpublicについてはUnityで特別な位置付けにあるので、C#での扱いとUnityでの扱いの両方を加味して選択するとグッド。
ゲーム開発の攻略チャートを作りました!
-
前の記事
【Unity/C#】継承やオーバーライドも使えると便利なのでぜひ 2021.01.30
-
次の記事
【サガフロ】ブルー編といえばラストが衝撃的過ぎたよね【THE END】 2021.02.01
コメントを書く