【正社員】還元率83%【フリーランス】マージン一律5万円で案件をご紹介させていただきます。 詳細はこちら

【Android】<Kotlin>インターフェース(interface)と抽象クラス(abstract class)の違いについてコード例を用いて徹底解説!

すだ

みなさまこんにちは〜!
メモリアインクのすだです。

Androidアプリを開発していく中で、「インターフェース」と「抽象クラス」という機能両方使う時があると思います。曖昧な理解のまま進めるには勿体無いほどそれぞれ便利な機能ですので、今日は両方の特徴と違いをしっかり捉えていきます。

この記事を読んでわかること…
・「インターフェース」と「抽象クラス」の特徴と違いについて

インターフェース、抽象クラスについては それぞれ以下記事で詳細にご詳細しておりますので
ぜひ合わせてご覧ください!

目次

環境

  • Kotlin (ver 1.9.0)
  • Android Studio (Giraffe | 2022.3.1 Patch 3)

インターフェースと抽象クラスの使い分け

インターフェースが「ルールだけを定義する契約書」であるのに対し、
抽象クラスは「ルールと共通機能がセットになったテンプレート」といえるでしょう。

また、わかりやすい違いといえば 以下のようなものがあります。

プロパティ

・インターフェース…プロパティの保持 不可
・抽象クラス…プロパティの保持

「プロパティの保持」とは「変数に値を入れて、あとで読み書きできる状態にすること」です。
たとえば、var name = "Taro"これは name というプロパティに "Taro" という状態(値)を持っているということです。

インターフェース

interface UserInfo {
    val id: String
}

インターフェースでは、上記のように定義はできますが、
これは中身(値)を持っておらず idというプロパティを持っていてねというルールを書くのみです。
値は各クラスで用意する必要があります。

抽象クラス

abstract class BaseUser {
    val id: String = "1"
}

それに対し抽象クラスでは、上記のように変数に値を持たせることができます。
このように、共通データや状態を持ちたい時に 抽象クラスは便利です。

コストラクタ

・インターフェース…コンストラクタ なし
・抽象クラス…コンストラクタ あり

コンストラクタ(constructor)とは、クラスを使うときに最初に呼ばれる「初期化のしくみ」です。

インターフェース

interface UserInfo {
    // val id: String ← これはルールとしては書けるが、初期化できない
}

インターフェースには、上記のようにコンストラクタ機能が存在しません。

抽象クラス

abstract class BaseUser(val id: String) {
    fun showId() {
        println("ユーザーID: $id")
    }
}

対して抽象クラスは、コンストラクタを使うことができます。

上記のように、共通のプロパティ(= id)を親の段階で初期化して、
以下のように子クラスで使うことができます。

class PremiumUser(id: String) : BaseUser(id)

PremiumUser を作るときに id を渡せば、
BaseUser 側のプロパティもすでに使える状態で継承されているというわけです。▼

val user = PremiumUser("abc123")
user.showId()  // → ユーザーID: abc123
  1. PremiumUser を作るときに id を受け取る
  2. その id を 親クラス(BaseUser)に渡す
  3. すると、BaseUser にあるプロパティ id に値がセットされる

多重実装(複数使用)

・インターフェース…多重実装OK
・抽象クラス…単一継承

インターフェースは 「処理を持たない設計ルール」なので共存ができるため、多重実装が可能であるのに対し
抽象クラスは実装の中身があるため、重複すると混乱することから単一継承しかできません。

インターフェース

interface Clickable {
    fun click()
}

interface Touchable {
    fun touch()
}

class Button : Clickable, Touchable {
    override fun click() {
        println("クリックされました")
    }

    override fun touch() {
        println("タッチされました")
    }
}

抽象クラス

open class Animal
open class CanFly

// × エラーになる
class Bird : Animal(), CanFly() 

どのシーンでどちらを使うべきか

インターフェース(interface)

・共通の動作ルールだけ決めたいとき
(→ 複数継承できる/ルールの明示に強いから)

・他のクラスと組み合わせたい
(→ FragmentやViewModelなど複数クラス設計に向くから)

抽象クラス(abstract class)

・共通処理や状態も持たせたいとき
(→ 共通関数・プロパティを1つにまとめられるから)

・共通のベース構造を作りたいとき
(→ 画面・処理ごとの共通フローに便利だから)

まとめ

おつかれさまでした。いかがでしたでしょうか!

「ルールだけなら interface」
「状態や共通処理もまとめたいなら abstract class」
という考え方です。

実務では 両方を併用する設計も多く、「設計の意図に応じて使い分ける」のがベストです。

すだ

技術者としてのキャリアパスを次のレベルへと進めたい皆様、
未経験からIT・Webエンジニアを目指すなら【ユニゾンキャリア】
を通じて、
自分の市場価値をさらに向上させてみませんか?

それではまた次回の記事でお会いしましょう!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

弊社テックブログをご愛読いただきありがとうございます。
当テックブログを運用している株式会社メモリアインクは、
【正社員】還元率83%
【フリーランス】マージン一律5万円で案件のご紹介
と、エンジニアの皆様に分かりやすい形で稼げる仕組みを構築し提供させていただいております。

コメント

コメントする

目次