ProgrammingKotlin 開発者

Kotlinにおいて、通常のクラス、抽象クラス、インターフェースはどのように異なり、いつどのツールを適用すべきか?

Hintsage AIアシスタントで面接を突破

回答。

問題の歴史:

KotlinはJavaとJVMの機能的な遺産の最良の側面を組み合わせました。通常のクラスは標準的な構造として宣言され、抽象クラスはデフォルト実装を持つ未定義のテンプレートを作成することを可能にし、インターフェースは状態を持たない振る舞いの多重継承をサポートします。

問題点:

クラス、抽象クラス、インターフェースの間での正しい選択は、アプリケーションのアーキテクチャ、コードの細分化、および拡張性を決定します。不適切な継承は、テストの難しさや将来の変更を引き起こす可能性があります。

解決策:

Kotlinでは、

  • 通常のクラス: 構造と振る舞いを定義します。openを宣言すると継承可能です。
  • 抽象クラス: 直接的には作成できません。実装や抽象的(ボディのない)メソッドを含むことができます。
  • インターフェース: 暗黙的にオープンで、契約を実装し、メソッドの実装を許可しますが、状態を保持しません(バックフィールドのないプロパティのみ)。

コードの例:

interface Drawable { fun draw() } abstract class Shape(var color: String) : Drawable { abstract fun calcArea(): Double override fun draw() = println("Shape drawn") } class Circle(color: String, val radius: Double) : Shape(color) { override fun calcArea() = Math.PI * radius * radius }

重要な特徴:

  • インターフェースは多重実装を許可し、抽象クラスは一度だけの実装を許可します。
  • インターフェースは状態を保持できず、抽象クラスは保持できます。
  • 抽象クラスはインターフェースの一部を実装し、独自の共通ロジックを持つことができます。

ツイストのある質問。

インターフェースはバックフィールドを持つプロパティを含むことができますか?

いいえ、プロパティのシグネチャを定義することはできますが、データを保持することはできません。このため、バックフィールドのないプロパティのみです。

複数のクラスから継承することはできますか?

いいえ、Kotlinはクラスの単一継承のみをサポートしますが、インターフェースの多重実装をサポートします。

インターフェースにコンストラクタを宣言できますか?

いいえ、インターフェースはコンストラクタをサポートしません。なぜなら、状態を保持しないからです—単なる振る舞いの契約なのです。

タイプエラーとアンチパターン

  • 必要がないのにインターフェースの代わりに抽象クラスを使用すること。
  • インターフェースに状態を保持すること。(不可能ですが、設計時に間違えます)
  • 拡張を難しくするクラスの階層を設計すること。

実生活の例

ネガティブケース

アプリケーションの全ての共通機能を抽象クラスに移し、内部ロジックや状態がない場合でも、単なる共通の契約が必要な場合です。

長所:

  • 共通ロジックの一箇所での変更

短所:

  • 多重継承の問題、他の構造との統合が難しい

ポジティブケース

必要な契約のみをインターフェースに移し、抽象クラスは実装が必要な共通のプロパティとメソッドに制限しました。

長所:

  • 柔軟な拡張性、モジュール性、クリーンな契約

短所:

  • 早期段階での設計が必要