はじめに
この記事を読めば、Kotlinのアクセス修飾子の使用方法やその詳細を習得することができるようになります。
アクセス修飾子とは何か、どのように使うのか、どのような場合に使うべきなのか、それに加えて、どのように活用するかについて、初心者目線でわかりやすく解説しています。
実用的な19のサンプルコードも紹介し、どのような場面でどの修飾子を使うべきかについても具体的に説明します。
●Kotlinのアクセス修飾子とは
Kotlinでコードを書く際に、変数やメソッド、クラスなどがどれだけ外部からアクセス可能かを制御するためのキーワードを「アクセス修飾子」と言います。
○アクセス修飾子の基本概念
Kotlinにおける主なアクセス修飾子は、public
、private
、protected
、internal
の4つです。
それぞれがどのようなアクセスレベルを持つのかについて説明します。
- public:この修飾子がついた要素は、どこからでもアクセス可能です。実は、Kotlinではこの修飾子がデフォルトです。つまり、明示的に修飾子を指定しない場合、
public
として扱われます。 - private:
private
修飾子がついた要素は、宣言された同じファイル内か、同じクラス内からしかアクセスできません。 - protected:
protected
は、主にクラス内とそのサブクラス内からアクセスできるようにする修飾子です。ただし、トップレベルの宣言(クラス外部の変数や関数)には使えません。 - internal:この修飾子がついた要素は、同じモジュール内からアクセス可能です。
●アクセス修飾子の使い方
アクセス修飾子の概念を押さえたところで、次に進んで実際の使い方を見ていきましょう。
それでは、各種のアクセス修飾子を具体的なサンプルコードとともに紹介します。
○サンプルコード1:public修飾子の使用例
Kotlinではpublic
がデフォルトの修飾子であり、明示的に指定しなくても他のどの場所からでもアクセスできるようになっています。
このサンプルコードではPublicClass
クラスとその中のshow
関数がpublic
と明示してあります。
この場合でも、public
を省略しても同じ意味になります。このクラスと関数はどこからでもアクセス可能です。
○サンプルコード2:private修飾子の使用例
private
修飾子は、宣言された要素がその宣言がされているブロック内でのみアクセス可能であることを意味します。
このコードで定義されたPrivateExample
クラスには、privateVar
というprivate
な変数があります。
この変数はクラス外から直接アクセスすることができません。
そのため、main
関数内でexample.privateVar
と書くとエラーになります。
ただし、クラス内のshowPrivateVar
関数を使って値を表示することはできます。
これらのコードを実行すると、Private Var = 1
という結果が得られます。
privateVar
はPrivateExample
クラス内でしかアクセスできないため、このような挙動となります。
○サンプルコード3:protected修飾子の使用例
次に紹介するprotected
修飾子は、その名前が示す通り保護された範囲でのみアクセスを許可します。
具体的には、そのクラス自身とそのクラスを継承したサブクラスからアクセスが可能です。
外部のクラスからはアクセスすることはできません。
このサンプルコードにおいては、Parent
クラスがprotected
な変数name
を持っており、Child
クラスがそれを継承しています。
Child
クラスのメソッドであるchangeName
はこのname
変数にアクセスして値を変更しています。
一方で、Parent
クラス外部からはname
に直接アクセスできないため、値の変更はChild
クラスを通して行います。
このコードを実行すると、最初にName in Parent: Parent
と出力され、その後にChild
クラスのname
が親クラスのname
と同じであることを確認できます。
さらに、changeName
関数を用いて名前をChanged
に変更後、Name in Child: Changed
と出力されるのが確認できます。
このように、protected
な変数はサブクラスでも利用可能です。
○サンプルコード4:internal修飾子の使用例
Kotlinでは、モジュール内での可視性を制御するためのinternal
修飾子も用意されています。
この修飾子は、同じモジュール内であればどこからでもアクセスできるようにします。
ここで出てくるInternalClass
は、internal
修飾子によって同一モジュール内からはアクセス可能な状態になっています。
main
関数内でInternalClass
のインスタンスを作成し、そのid
プロパティにアクセスしています。
このコードを実行すると、ID: 1
と表示されます。
これはinternal
修飾子によって、同じモジュール内からアクセスできるためです。
●アクセス修飾子の応用例
基本的な使い方に慣れたところで、アクセス修飾子の応用例について解説していきます。
独自のクラス設計やモジュール設計を行う際に、アクセス修飾子をどのように活用できるかを具体的なサンプルコードとともに紹介します。
○サンプルコード5:クラス外からのアクセス制限
通常、プロパティやメソッドが外部からアクセスできるかどうかを制限する場面があります。
下記の例では、BankAccount
クラスにprivate
修飾子を用いて、balance
プロパティへの直接アクセスを制限しています。
この例ではBankAccount
クラス内でのみbalance
にアクセスできます。
deposit
メソッドを通じてのみ、balance
を操作できる設計になっています。
main
関数でaccount.showBalance()
を呼び出すと、”残高は5000 円です。”と出力されます。
一方で、account.balance = 10000
のような直接的な操作はコンパイルエラーとなります。
○サンプルコード6:同じモジュール内からのアクセス
複数のクラスやファイルが同じモジュールに属している場合、その中で共有したいプロパティやメソッドが出てくることがあります。
そのような場合はinternal
修飾子を使うと便利です。
こちらのサンプルコードでは、SharedResource
クラスがinternal
修飾子によって同一モジュール内でアクセス可能な状態になっています。
main
関数でSharedResource
のインスタンスを作成し、data
プロパティにアクセスしています。
このコードを実行すると最初に”Data: Initial Data”が出力され、その後に”Data: Updated Data”が出力されます。
○サンプルコード7:サブクラスからのアクセス
クラス階層において、親クラスのプロパティやメソッドをサブクラスで参照または操作する際に有用な修飾子がprotected
です。
この修飾子を使うと、親クラスのプロパティやメソッドがサブクラスからは参照できるが、それ以外のクラスからは参照できなくなります。
このコードでは、親クラスAnimal
にprotected
で定義されたプロパティsound
があります。
Dog
クラス(サブクラス)では、このsound
プロパティに直接アクセスし、その値を”Woof”に変更しています。
main
関数を実行すると、”Animal makes Woof”と”Dog says Woof”が順番に出力されます。
一方で、myDog.sound
のようにmain
関数から直接sound
プロパティにアクセスしようとするとコンパイルエラーになります。
○サンプルコード8:同じファイル内からのアクセス
同じKotlinファイル内であれば、アクセス修飾子を省略(デフォルトはpublic
)したり、private
を指定してもそのファイル内から自由にアクセスできます。
この特性は、小規模なプログラムやスクリプトで特に有用です。
この例ではSampleClass
というクラスに二つのプロパティがあります。
一つは修飾子なしで定義されたvisibleToEveryone
、もう一つはprivate
修飾子で定義されたvisibleInThisFile
です。
同じファイル内のshow
関数からは、どちらのプロパティも問題なくアクセスできます。
main
関数を実行すると、”Public says: I am Public”が出力された後に”Public says: I am Public, Private says: I am Private”が出力されます。
●アクセス修飾子を活用したコード設計
アクセス修飾子の基本的な使い方や応用例を学んだ後、今度はより高度なコード設計に焦点を当てます。
アクセス修飾子は、単に変数や関数に制限をかける以上のものです。
それをうまく使うことで、プログラム全体の安全性とメンテナンス性を高めることができます。
○サンプルコード9:モジュール間のデータのやり取り
モジュールとは、プログラムの一部分を独立させたものです。
internal
修飾子は、同じモジュール内でのみアクセスを許可するため、モジュール間のデータのやり取りに役立ちます。
このコード例では、ModuleA
というクラスがinternal
修飾子で宣言されています。
このクラスは、同じモジュール内(この場合は同じファイル内)であれば自由に使うことができます。
main
関数でもModuleA
のshow
メソッドを呼び出し、”This is ModuleA”と出力されます。
○サンプルコード10:継承を考慮した設計
クラスの継承を行う場合、親クラスのプロパティやメソッドにどのようなアクセス修飾子を設定するかが重要です。
例えば、親クラスのメソッドをサブクラスでオーバーライドしたい場合、open
キーワードを使ってそのメソッドをオーバーライド可能にします。
このコードでは、Parent
クラスにopen
修飾子が付いており、showMessage
メソッドも同様にopen
で宣言されています。
これによりChild
クラスではshowMessage
をオーバーライドできます。
main
関数で各インスタンスのshowMessage
を呼び出すと、それぞれのクラスに合わせたメッセージが出力されます。
○サンプルコード11:内部クラスのアクセス制限
Kotlinでは、クラス内にさらにクラスを定義することができます。
これを内部クラスと呼びます。内部クラスにもアクセス修飾子を指定することができ、それによって内部クラスのアクセス範囲を制限することが可能です。
このサンプルコードでは、OuterClass
内にInnerClass
という内部クラスを定義しています。
そして、この内部クラスにprivate
修飾子を指定しています。
このため、InnerClass
はOuterClass
からしかアクセスできません。
accessInner
メソッドでは、InnerClass
のインスタンスを作成してinnerMethod
を呼び出しています。
このinnerMethod
はInnerClass
内で定義されたメソッドで、”This is inner method.”と出力されます。
main
関数でOuterClass
のインスタンスを作成し、accessInner
メソッドを呼び出しています。
結果として、”This is inner method.”という出力が得られます。
○サンプルコード12:拡張関数とアクセス修飾子
Kotlinでは、既存のクラスに新しいメソッドを追加することができる拡張関数があります。
この拡張関数にもアクセス修飾子を適用することができます。
このコードでは、String
クラスにaddExclamation
という拡張関数を追加しています。
この拡張関数はprivate
修飾子が指定されているため、同じファイル内からのみアクセス可能です。
main
関数でこの拡張関数を呼び出すと、”Hello!”という出力が得られます。
●注意点と対処法
アクセス修飾子の使用にはいくつか注意すべきポイントがあります。
コーディングの際に問題を回避するために、これらの注意点とその対処法を理解しておくことが重要です。
○サンプルコード13:意図しないアクセスを避ける
アクセス修飾子を適切に設定しないと、予期せぬ場所からクラスやメソッドにアクセスされる可能性があります。
このコードのDangerousClass
は、sensitiveData
という重要なデータを持っていますが、アクセス修飾子が設定されていないため、どこからでもアクセス可能です。
この問題を解決する一例として、private
修飾子を使います。
このように修正すると、sensitiveData
にはSafeClass
内からしかアクセスできなくなります。
○サンプルコード14:修飾子の組み合わせの注意点
Kotlinでは複数の修飾子を組み合わせることがありますが、その際には注意が必要です。
このコードではprivate
とopen
が組み合わされていますが、これは矛盾しています。
open
は継承を許可する修飾子なので、private
と併用することはできません。
○サンプルコード15:アクセス修飾子のオーバーライド
親クラスに設定されたアクセス修飾子は、子クラスでオーバーライドする際には維持されます。
しかし、それを変更することもできます。
このコードでは、Parent
クラスにprotected
でshow
メソッドが定義されています。
このshow
メソッドは、Child
クラスでpublic
にオーバーライドされています。
main
関数でChild
クラスのインスタンスを作成し、show
メソッドを呼び出すと、「This is parent class.」「This is child class.」と出力されます。
●カスタマイズ方法
Kotlinのアクセス修飾子は基本的なものから応用的な使い方まで多岐にわたりますが、それだけでなく、さらに高度なカスタマイズも可能です。
ここでは、そのような高度な利用法について詳しく説明します。
○サンプルコード16:カスタムアクセス修飾子の作成
Kotlinでは、直接アクセス修飾子をカスタムすることはできませんが、特定の動作をする関数を作って、それをアクセス制御に使用することはできます。
このコードで注目すべきはcustomAccessControl
関数です。
この関数は引数user
を受け取り、その値が”admin”であればtrue
を、それ以外であればfalse
を返します。
この関数を使ってCustomAccessClass
内のrestrictedFunction
メソッドでアクセス制御を行っています。
main
関数を実行すると、”admin”では「アクセス許可」、”guest”では「アクセス拒否」と表示され、カスタムアクセス制御が正しく動作していることがわかります。
○サンプルコード17:特定のクラスや関数にのみアクセスを許可する
Kotlinでは、特定のクラスや関数にだけアクセスを許可するような細かい制御も可能です。
そのためには、拡張関数や高階関数を用いる方法があります。
このコードではSpecialClass
クラス内にspecialFunction
というprivate
メソッドがあります。
これは通常、クラス外からは呼び出せません。
しかし、accessFrom
というメソッドを通じて、specialFunction
を呼び出すことができます。
このようにして、特定の関数やクラスからのみアクセスを許可することが可能です。
○サンプルコード18:ライブラリのアクセス制限のカスタマイズ
Kotlinを使っていると、外部ライブラリを多用するケースも多くあります。
外部ライブラリは便利な一方で、必要以上に多くの機能が公開されていることがあります。
これをカスタムアクセス修飾子と組み合わせて制御する方法を見ていきましょう。
このコードでは、LibraryClass
をシミュレーションしています。
このクラスにはpublicMethod
、internalMethod
、privateMethod
の三つのメソッドがあります。
続いてCustomLibraryClass
クラスでLibraryClass
を継承しています。
ここではpublicMethod
をオーバーライドしており、何らかの制御を行っています。
main
関数を実行すると、publicMethod
がオーバーライドされたものが呼び出され、「Public method in library」と出力されます。
続いてcustomMethod
が呼び出され、「This is a custom method.」と出力されます。
○サンプルコード19:アノテーションとアクセス修飾子の組み合わせ
アクセス修飾子だけでなく、アノテーションを使用することで、さらに繊細なアクセス制御が可能です。
このコードでは、@SpecialPermission
というアノテーションを定義しています。
そしてAnnotationControl
クラスのspecialFunction
メソッドにこのアノテーションを付与しています。
executeFunctionWithPermission
関数では、メソッドに@SpecialPermission
アノテーションが付与されているかどうかをチェックしています。
main
関数を実行すると、specialFunction
メソッドに@SpecialPermission
アノテーションが付与されているので、このメソッドが実行され、「This function needs special permission.」と出力されます。
まとめ
この記事でKotlinのアクセス修飾子について、初心者にもわかるように詳細に解説してきました。
Kotlinでは、これらの修飾子を使ってコードの安全性を高め、保守性を向上させることが可能です。
Kotlinのアクセス修飾子は、プログラミングスキル全体を向上させる手段の一つと言えるでしょう。
これからもKotlinの様々な機能を学んで、より効率的かつ安全なコードを書く力を身に付けていきましょう。
それでは、この記事の内容が皆さんのKotlinでのプログラミングライフに役立つことを心より願っています。