【Kotlin】レッスン5-03:セカンダリコンストラクタを理解しよう

記事内に商品プロモーションを含む場合があります

この記事で学べる知識:セカンダリコンストラクタ

この記事の練習問題を解くために必要な知識:
基礎文法、制御構造、関数、コレクション(レッスン1~4)クラスの定義と使用プライマリコンストラクタセカンダリコンストラクタアクセス修飾子とカプセル化クラスメンバとインスタンスメンバクラスの継承メソッドのオーバーライドクラスの拡張抽象クラスインターフェースデータクラス

<<前のページ Kotlin記事一覧 次のページ>>

Kotlinの「セカンダリコンストラクタ」とは

この章ではKotlinにおける「セカンダリコンストラクタ」の意味や使い方を学習します。用語の解説が不要な方はここをクリックして練習問題へ飛びましょう。




Kotlinにはクラスの初期化方法としてプライマリコンストラクタセカンダリコンストラクタの2種類があります。

本記事では、セカンダリコンストラクタについて詳しく解説します。

これにより、複雑な初期化処理が必要な場合でも柔軟に対応できるようになります。

【初心者向け】Kotlinのオブジェクト指向を分かりやすくまとめた概念図。 特にクラスの継承、オーバーライド、抽象クラス、インターフェース、データクラスの関係性を視覚的に理解できるようまとめている。

セカンダリコンストラクタとは?

セカンダリコンストラクタは、プライマリコンストラクタとは異なる形でオブジェクトを初期化するための方法です。

特に、以下の場合に使用されます:

  • プライマリコンストラクタでは対応できない初期化処理が必要なとき。
  • オーバーロードされた複数の初期化方法を提供したいとき。

セカンダリコンストラクタを利用することで、異なる初期化パラメータや処理を柔軟に対応可能です。

【Kotlin】レッスン3-05:関数のオーバーロードを理解しよう【Kotlin】関数のオーバーロードを習得するためのオンライン教材&練習問題。関数のオーバーロードという言葉の意味やコードの中での役割を、勉強を始めて間もない人のために簡潔にまとめています。シンプルな練習問題を使ってKotlinの基本が身に付きますので、一度覗いてみてください。...

セカンダリコンストラクタの基本構文

セカンダリコンストラクタは、constructorキーワードを用いて定義します。

以下は基本構文です:

class クラス名 {
    constructor(引数: 型, ...) {
        // セカンダリコンストラクタの処理
    }
}

セカンダリコンストラクタは、必要に応じてthisを使用して他のコンストラクタを呼び出すことができます。(下記参照)

これにより、コードの再利用性が向上します。

セカンダリコンストラクタの使用例

以下は、セカンダリコンストラクタの実際の使用例です。

class User {
    var name: String
    var age: Int

    // セカンダリコンストラクタ1(引数なし)
    constructor() {
        this.name = "Default Name" // デフォルトの名前を設定
        this.age = 0               // デフォルトの年齢を設定
    }

    // セカンダリコンストラクタ2(引数あり)
    constructor(name: String, age: Int) {
        this.name = name          // 引数で渡された名前を設定
        this.age = age            // 引数で渡された年齢を設定
    }
}

fun main() {
    // セカンダリコンストラクタ1を使用してオブジェクトを作成
    val user1 = User()
    println("User1: 名前=${user1.name}, 年齢=${user1.age}")

    // セカンダリコンストラクタ2を使用してオブジェクトを作成
    val user2 = User("Alice", 25)
    println("User2: 名前=${user2.name}, 年齢=${user2.age}")
}
  1. constructor()は引数を受け取らず、デフォルト値を設定します。
  2. constructor(name: String, age: Int)は引数で受け取った値をプロパティに設定します。
  3. それぞれのコンストラクタを使用して異なる方法でUserオブジェクトを作成しています。

このコードを実行すると以下のように出力されます。

User1: 名前=Default Name, 年齢=0
User2: 名前=Alice, 年齢=25

このように、セカンダリコンストラクタを利用することで、より柔軟な初期化が可能になります。

セカンダリコンストラクタを使用するメリット

  1. 柔軟な初期化: プライマリコンストラクタでは対応できない初期化処理を実現。
  2. コードの再利用: thisキーワードを活用し、他のコンストラクタを呼び出すことで冗長なコードを回避。
  3. 互換性: JavaのコードをKotlinに移行する際、セカンダリコンストラクタを使用することで互換性を保てる。

ただし、Kotlinではプライマリコンストラクタやinitブロックの使用が推奨される場合が多いため、セカンダリコンストラクタは必要な場面でのみ使用するよう心がけましょう。

セカンダリコンストラクタの練習問題:簡単な電卓クラスを作ろう

クラスを使用して簡単な電卓プログラムを作成しましょう。

電卓クラスではセカンダリコンストラクタを使って初期値を設定します。また2種類の「add」メソッドを定義して、それぞれ1つの値と2つの値を足すことができます。

このプログラムを通じてセカンダリコンストラクタと関数のオーバーロードを習得しましょう。

この問題の要件

以下の要件に従ってコードを完成させてください。

  1. クラスの定義
    • Calculator というクラスを定義すること。
    • クラス内に整数型の変数 result を定義し、計算結果を格納すること。
  2. セカンダリコンストラクタ
    • セカンダリコンストラクタを使って Calculator を初期化し、初期値を設定すること。
  3. 関数のオーバーロード:add という名前の関数を2種類定義すること。
    • バージョン1: 1つの整数を受け取り、その値を result に加える。
    • バージョン2: 2つの整数を受け取り、その合計値を result に加える。
  4. メイン関数
    • 初期値を10として Calculator クラスをインスタンス化すること。
    • add メソッドを使って以下の計算を行うこと:
      • 5 を加算する。
      • 37 を加算する。
    • 計算結果をそれぞれ表示すること。

ただし、以下のような実行結果となるコードを書くこと。

*****↓↓正解コードの実行結果の例↓↓*****

初期値が設定されました: 10
値 5 を加えました。現在の結果: 15
値 3 と 7 を加えました。現在の結果: 25
最終的な計算結果: 25

この問題を解くヒント

1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。

ヒント1【コードの構成を見る】

正解のコードは上から順に以下のような構成となっています。
(※下記の□はコード内のインデントを表しています)

1:Calculatorクラスを定義
  □ 変数resultをInt型で定義し、初期値0を設定
  □ セカンダリコンストラクタを定義し、引数initialValueを受け取る
  □ □ resultにinitialValueを代入
  □ □ 初期値が設定されたことをprintlnで出力
  □ 関数addをオーバーロードし、1つ目のバージョンを定義
  □ □ 引数valueを受け取り、resultに加算
  □ □ 加算後の結果をprintlnで出力
  □ 関数addをオーバーロードし、2つ目のバージョンを定義
  □ □ 引数value1とvalue2を受け取り、それらの合計をresultに加算
  □ □ 加算後の結果をprintlnで出力
2:main関数を定義
  □ Calculatorクラスのインスタンスを生成し、初期値10を設定
  □ add関数を呼び出し、値5を加算
  □ add関数を呼び出し、値3と7を加算
  □ 最終的な計算結果をprintlnで出力

ヒント2【穴埋め問題にする】

以下のコードをコピーし、コメントに従ってコードを完成させて下さい。

// クラスの定義
// このクラスは簡単な計算を行うツールです
class Calculator {
    var result: Int = 0 // 計算結果を格納する変数

    // セカンダリコンストラクタ
    /*【穴埋め問題1】
    ここにセカンダリコンストラクタの定義を記述してください。
    引数に初期値を取り、それをresultに代入し、初期値を出力するコードを書いてください。
    */

    // 関数のオーバーロード: 足し算を行います
    // バージョン1: 1つの値を足す
    /*【穴埋め問題2】
    ここに1つの値をresultに加算し、加算後の結果を出力するadd関数を定義してください。
    */

    // バージョン2: 2つの値を足す
    /*【穴埋め問題3】
    ここに2つの値をresultに加算し、加算後の結果を出力するadd関数を定義してください。
    */
}

fun main() {
    // Calculatorクラスのインスタンスを生成(初期値10を設定)
    val calculator = Calculator(10)

    // 1つの値を加算
    calculator.add(5)

    // 2つの値を加算
    calculator.add(3, 7)

    // 最終結果を表示
    println("最終的な計算結果: ${calculator.result}")
}

以上がこの問題の穴埋めコードです。

このヒントを見てもまだ回答を導き出すのが難しいと感じる場合は、先に正解のコードと解説を見て内容を理解するようにしましょう。



練習問題の解答と解説

この問題の一つの正解例とそのコードの解説を以下に示します。

正解コードの例

例えば以下のようなプログラムが考えられます。

// クラスの定義
// このクラスは簡単な計算を行うツールです
class Calculator {
    var result: Int = 0 // 計算結果を格納する変数

    // セカンダリコンストラクタ
    constructor(initialValue: Int) {
        this.result = initialValue
        println("初期値が設定されました: $initialValue")
    }

    // 関数のオーバーロード: 足し算を行います
    // バージョン1: 1つの値を足す
    fun add(value: Int) {
        result += value
        println("値 $value を加えました。現在の結果: $result")
    }

    // バージョン2: 2つの値を足す
    fun add(value1: Int, value2: Int) {
        result += value1 + value2
        println("値 $value1 と $value2 を加えました。現在の結果: $result")
    }
}

fun main() {
    // Calculatorクラスのインスタンスを生成(初期値10を設定)
    val calculator = Calculator(10)

    // 1つの値を加算
    calculator.add(5)

    // 2つの値を加算
    calculator.add(3, 7)

    // 最終結果を表示
    println("最終的な計算結果: ${calculator.result}")
}

正解コードの解説

このコードはセカンダリコンストラクタを使って簡単な電卓クラスを作成しています。

ブロックごとにコードを分解し、それぞれの部分を詳しく解説します。

クラスの定義

class Calculator {
    var result: Int = 0 // 計算結果を格納する変数
  • class Calculator:Calculator というクラスを定義しています。クラスはオブジェクト指向プログラミングの基本単位で、関連するデータ(プロパティ)と操作(メソッド)をまとめたものです。
  • var result: Int:整数型の result をプロパティとして宣言しています。このプロパティは計算の結果を保持します。

セカンダリコンストラクタ

constructor(initialValue: Int) {
    this.result = initialValue
    println("初期値が設定されました: $initialValue")
}
  • constructor(initialValue: Int):引数 initialValue を受け取り、result プロパティに代入しています。
  • this.result = initialValue:this キーワードは、クラス内のプロパティやメソッドを指します。この場合、result プロパティに値を設定しています。
  • println():初期化が正常に行われたことをコンソールに表示します。

関数のオーバーロード

fun add(value: Int) {
    result += value
    println("値 $value を加えました。現在の結果: $result")
}

fun add(value1: Int, value2: Int) {
    result += value1 + value2
    println("値 $value1 と $value2 を加えました。現在の結果: $result")
}
  • fun add(value: Int):1つの引数を受け取り、その値を result に加えます。
  • fun add(value1: Int, value2: Int):2つの引数を受け取り、その合計を result に加えます。
  • 両方の関数で result の値を更新し、現在の計算結果をコンソールに表示します。

メイン関数

fun main() {
    val calculator = Calculator(10)
    calculator.add(5)
    calculator.add(3, 7)
    println("最終的な計算結果: ${calculator.result}")
}
  • val calculator = Calculator(10):初期値を10として Calculator クラスをインスタンス化します。このときセカンダリコンストラクタが呼び出されます。
  • calculator.add(5):引数 5 を渡し、add メソッドで1つの値を加算します。
  • calculator.add(3, 7):引数 37 を渡し、add メソッドで2つの値を加算します。
  • println():最終的な計算結果をコンソールに表示します。

まとめ

このコードではセカンダリコンストラクタを活用して、初期値を設定する方法を学びました。

また関数のオーバーロードを使用して異なる操作を簡潔に実現しました。

セカンダリコンストラクタは柔軟な初期化を可能にし、関数のオーバーロードはコードの再利用性を高めます。

これらの知識はより複雑なプログラムを作成する際に非常に役立ちます。次の記事では、二つのコンストラクタを同時に実装してみましょう。

<<前のページ Kotlin記事一覧 次のページ>>

この記事への質問・コメント

この記事を作成するにあたりAIを活用しています。

問題ないことは確認していますが、もし間違いや表現の違和感などありましたら、ご指摘頂けると大変助かります。






    Kotlinのテキスト&問題集トップへ戻る
    トップページへ戻る