
みなさまこんにちは〜!
メモリアインクのすだです。
Androidアプリを開発していく中で、「インターフェース(interface)」という機能を使う時があると思います。きちんとした理解を持って使用すれば、とても便利な機能なので 今日は一緒に学んでいきましょう。
この記事を読んでわかること…
・インターフェース(interface)とは?
・Kotlinでの開発におけるインターフェース(interface)の使い方
環境
- Kotlin (ver 1.9.0)
- Android Studio (Giraffe | 2022.3.1 Patch 3)
インターフェース(interface)とは?
アプリ開発におけるインターフェース(interface)とは、
「クラス(class)に”これを実装してね”と約束を与える設計図」のことです。
実際の処理は書かず、「こういう関数を持ってね」という命令だけを書き、
実装はそのクラス自身が行います。(= 自由に中身を書ける)
なぜインターフェースを使うのか?
「クラスだけでも動くのに、なぜあえてインターフェース(interface)を使うのか?」
これは多くの人が一度は疑問に思うポイントです。
結論から言うと、
「クラスでは実現できない柔軟さや設計のしやすさ」がインターフェースにはあるからです。▼
① 複数の異なるクラスに「共通の約束」を持たせられる
たとえば:
interface Clickable {
fun onClick()
}
このように用意した1つのinterfaceを…
class Button : Clickable { ... }
class Image : Clickable { ... }
class Text : Clickable { ... }
→このように複数クラスで共通利用することで、
ボタンも画像もテキストも「onClick() を持ってる」という共通のルールにできます。
どんな種類のクラスでも“同じ振る舞い”が保証されるというわけです。
② 多重継承ができる(クラスではできない)
Kotlinではクラスは1つしか継承できませんが、インターフェースなら何個でも実装できます。
interface Clickable { fun onClick() }
interface Focusable { fun onFocus() }
class CustomView : Clickable, Focusable {
override fun onClick() { ... }
override fun onFocus() { ... }
}
「いろんな性質を持つ」クラスを柔軟に作れるのがインターフェースです。
③ テストやDI(依存性注入)で差し替えやすい
interface UserRepository {
fun getUserName(): String
}
本番ではAPI用、テストではモック用に差し替えができたりもします。
class ApiUserRepository : UserRepository { ... }
class FakeUserRepository : UserRepository { ... }
インターフェースを使えば、使い方は同じで中身だけ切り替えられるのです。
このように インターフェースは、
「何をするか」だけを決めて、実際の中身は自由に作れる “約束のしくみ”。
これによって、柔軟で、テストしやすく、再利用しやすい設計ができるようになります。
インターフェースの基本的な使い方
それでは、商用アプリをイメージして
「アプリが “メール通知” や “アプリ内通知”、”プッシュ通知” などを送るとき、
通知方法をインターフェースで切り替えられるようにする」という機能を簡単に実装してみます。
インターフェースの定義
interface Notifier {
fun send(message: String)
}
→「通知を送る機能は send(message) を持つ」というルールです。send()
は各通知方式で上書きしてもらうようにします。
実装クラス
class EmailNotifier : Notifier {
override fun send(message: String) {
println("メール送信: $message")
}
}
class InAppNotifier : Notifier {
override fun send(message: String) {
println("アプリ内通知: $message")
}
}
→ Notifierというインターフェースを共通で利用します。
ここで、インターフェースにある関数を自分用に書き換えるために override
と記述します。override
をつけることで、「この関数は親と同じ名前だけど、中身は自分用に書き換えるね」という宣言になります。
Activity内で実装クラスを利用
class MainActivity : AppCompatActivity() {
private lateinit var notifier: Notifier
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
notifier = EmailNotifier() // ← 簡単に切り替え可能
val button = findViewById<Button>(R.id.notifyButton)
val textView = findViewById<TextView>(R.id.resultText)
button.setOnClickListener {
val message = "キャンペーンのお知らせがあります!"
notifier.send(message)
textView.text = "通知を送りました"
}
}
}
→9行目で、Notifierインターフェースの実装クラス「EmailNotifier」のインスタンスを作成します。
そして、14行目のボタンクリック時処理で、notifier.send(message)
を通じてインターフェース経由でメールの送信処理(send関数)を行います。
補足
Kotlinの場合、インターフェースに実際の処理を書くこともできる
先ほど、「実際の処理は書かず、「こういう関数を持ってね」という命令だけ」とお伝えしましたが
実は Kotlinのインターフェースは
・「基本的には処理は書かない」という原則と、
・「書けるけど、必要なときだけ書く」という柔軟性
が両立しています。(つまり、kotlinではインターフェースに中身=処理 もかけるということです)
どういうことかというと…↓
インターフェースの本来の役割は「ルールづくり」
まず大前提として、
インターフェースは「このクラスはこういう機能を持っていてね」という約束(契約)を定義するものです。
たとえば:
interface Clickable {
fun click() // ← これは「必ずこの関数を持っててね!」というルール
}
→ ここに処理は不要。
→ 実際の処理は、各クラスごとに自由に書けるようにするのが目的。
コードの重複を減らせるため、必要があれば実処理を書く
しかしたとえば、
fun log(message: String) {
println("ログ出力: $message")
}
これを全クラスに書くのは面倒なので、
interface Loggable {
fun log(message: String) {
println("ログ出力: $message") // デフォルト実装
}
}
上記のようにインターフェース内で処理を書くことで、この関数を実装クラスで呼び出せばいつでもこの処理を通すことができます。
また、必要であればoverrideで上書きもできるので デフォルト処理として実装しておくのもよいでしょう。
基本的にはルールだけ書いておいておくものですが、共通処理が必要であれば中身を書くこともできるという柔軟性を持つのがKoltinのインターフェースです。
まとめ
おつかれさまでした。いかがでしたでしょうか!
インターフェースを活用することで、秩序ある整理されたコードを書くことができます。
設計段階からインターフェースの利用を前提に進めると、拡張性や保守性の高い開発につながるでしょう。



技術者としてのキャリアパスを次のレベルへと進めたい皆様、
<未経験からIT・Webエンジニアを目指すなら【ユニゾンキャリア】>
自分の市場価値をさらに向上させてみませんか?
それではまた次回の記事でお会いしましょう!
コメント