Kotlinの初心者向け問題4-2:ゲッターとセッターを使ってみよう
この問題を解くために必要な知識:
【レベル1~3の知識】
コメントの書き方、変数と定数、基本データ型、算術演算と論理演算、入力と出力、import文、配列、分岐処理(if、if~else、when)、繰り返し処理(for、while、do~while)、Null安全、スマートキャスト、関数の定義と呼び出し、関数の戻り値、関数のオーバーロード、ラベルとジャンプ、例外処理、クラスの定義と使用、インスタンス、コンストラクタ、プロパティ、クラスの継承、クラスの拡張、コレクションの基礎、リストコレクション(MutableList、ArrayList)、セットコレクション(HashSet、MutableSet、TreeSet)、マップコレクション(HashMap、MutableMap、TreeMap)、
【レベル4の知識】
メンバ関数、ゲッターとセッター、カプセル化、クラスメンバ、抽象クラス、インターフェース、データクラス
<<前の問題 | 問題集Top |
次の問題>> |
Kotlinの文法「ゲッターとセッター」とは
ここではゲッターとセッターの意味や使い方を復習します。必要ない方はここをクリックして練習問題へ飛びましょう。
Kotlinでオブジェクト指向プログラミングを学ぶ際、ゲッターとセッターは非常に重要な概念です。
これらは、クラスのプロパティに対して安全かつ簡潔なアクセスを提供するために使われます。
この記事では、Kotlinにおけるゲッターとセッターの基本的な仕組みとそのメリットについて説明します。
ゲッターとセッターとは?
ゲッターとセッターは、クラスのプロパティにアクセスしたり、その値を変更したりするためのメソッドです。
- ゲッターはプロパティの値を取得するメソッドです。
- セッターはプロパティの値を設定(変更)するメソッドです。
これらのメソッドを定義することで、直接プロパティにアクセスするのではなく、プロパティの読み書きに制御を加えることができます。
このアプローチにより、カプセル化が促進され、予期しないデータの変更や無効な値の設定を防ぐことができます。
Kotlinにおけるゲッターとセッターの定義
Kotlinでは、ゲッターとセッターはJavaのように手動で書く必要がありません。
Kotlinのプロパティは自動的にゲッターとセッターを持ちます。これにより、コードがシンプルかつ効率的になります。
class Person { var name: String = "John" get() = field // ゲッター set(value) { field = value // セッター } }
上記のコードでは、name
というプロパティに対してゲッターとセッターが定義されています。
get()
はプロパティの値を取得し、set()
は値を設定します。field
はプロパティ自体を指し、プロパティの値を操作する際に使います。
ゲッターとセッターの使用例
次に、実際にゲッターとセッターを使用する例を見てみましょう。
以下のコードは、Person
クラスを使ってプロパティの値を読み書きする例です。
fun main() { val person = Person() println(person.name) // ゲッターを使って名前を取得 person.name = "Alice" // セッターを使って名前を変更 println(person.name) // 新しい名前を取得 }
出力は以下のようになります:
John Alice
このように、name
プロパティにアクセスする際、実際にはKotlinが自動的にゲッターとセッターを呼び出してくれます。
これにより、プログラマはコードのシンプルさを保ちつつ、必要なときに柔軟に制御を加えることができます。
ゲッターとセッターを使うメリット
Kotlinのゲッターとセッターを使うことで、次のようなメリットがあります。
- カプセル化: データに直接アクセスする代わりに、メソッドを介して操作することで、内部状態を保護し、無効なデータの設定を防ぐことができます。
- 柔軟性: 必要に応じてゲッターやセッターの動作をカスタマイズできます。例えば、セッターで入力データの検証を行うことも可能です。
- 自動生成: Kotlinはプロパティに対して自動的にゲッターとセッターを作成するため、手動でコードを書く手間が省けます。
まとめ
Kotlinにおけるゲッターとセッターは、プロパティへのアクセスを簡単かつ安全にするための強力なツールです。
Kotlinが提供する自動的なゲッター・セッター機能により、コードの可読性と保守性が向上します。
また、必要に応じてこれらのメソッドをカスタマイズすることで、柔軟にデータ操作のロジックを追加できるのも魅力です。
オブジェクト指向プログラミングの基礎として、ぜひ理解を深めてみてください。
Kotlin練習問題4-2:ゲッターとセッターを使ってみよう
Kotlinのクラスとプロパティを使って、ゲッターとセッターを復習するためのプログラムを作成しましょう。
このプログラムでは、ユーザーの名前と年齢を管理する簡単なクラスを作成し、そのクラスを使用してユーザー情報を表示および更新する機能を実装します。
この問題の要件
以下の要件に従ってコードを完成させてください。
- ユーザー情報を管理するためのクラス
User
を作成すること。 User
クラスには、name
とage
プロパティを持たせること。name
プロパティには、カスタムゲッターとセッターを実装すること。- ゲッター:現在の名前を返す。
- セッター:新しい名前を設定するが、名前が空の場合は「名無し」に設定する。
age
プロパティには、カスタムゲッターとセッターを実装すること。- ゲッター:現在の年齢を返す。
- セッター:新しい年齢を設定するが、年齢が負の場合は0に設定する。
- メイン関数でユーザーのインスタンスを作成し、名前と年齢を表示および更新すること。
ただし、以下のような実行結果となること。
----- ↓出力される結果の例↓ -----
初期の名前: 名無し 初期の年齢: 0 更新後の名前: 太郎 更新後の年齢: 25 空文字設定後の名前: 名無し 負の値設定後の年齢: 0
----- ↑出力される結果の例↑ -----
この問題を解くヒント
1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。
正解のコードは上から順に以下のような構成となっています。
1.Userクラスの定義
1-1. nameプロパティの定義とカスタムゲッターおよびセッター
1-1-1. プロパティnameの初期値を”名無し”に設定
1-1-2. ゲッター:現在のnameを返す
1-1-3. セッター:新しいnameを設定。空の場合は”名無し”に設定
1-2. ageプロパティの定義とカスタムゲッターおよびセッター
1-2-1. プロパティageの初期値を0に設定
1-2-2. ゲッター:現在のageを返す
1-2-3. セッター:新しいageを設定。負の場合は0に設定
2.main関数の定義
2-1. Userクラスのインスタンスを作成
2-2. 初期のnameとageを表示
2-3. nameとageを更新
2-3-1. nameを”太郎”に設定
2-3-2. ageを25に設定
2-4. 更新後のnameとageを表示
2-5. nameを空文字に設定し、結果を表示
2-6. ageを負の値に設定し、結果を表示
以下のコードをコピーし、コメントに従ってコードを完成させて下さい。
// ユーザークラスの定義 class User { // プロパティ 'name' の定義とカスタムゲッターおよびセッター var name: String = "名無し" get() { // ***【穴埋め問題1】ここにゲッターとして現在の名前を返すコードを書いてください *** } set(value) { // ***【穴埋め問題2】ここにセッターとして新しい名前を設定するコードを書いてください *** } // プロパティ 'age' の定義とカスタムゲッターおよびセッター var age: Int = 0 get() { // ***【穴埋め問題3】ここにゲッターとして現在の年齢を返すコードを書いてください *** } set(value) { // ***【穴埋め問題4】ここにセッターとして新しい年齢を設定するコードを書いてください *** } } // メイン関数 fun main() { // Userクラスのインスタンスを作成 val user = User() // 初期の名前と年齢を表示 println("初期の名前: ${user.name}") println("初期の年齢: ${user.age}") // 名前と年齢を更新 user.name = "太郎" user.age = 25 // 更新後の名前と年齢を表示 println("更新後の名前: ${user.name}") println("更新後の年齢: ${user.age}") // 名前を空文字にして設定 user.name = "" println("空文字設定後の名前: ${user.name}") // 年齢を負の値にして設定 user.age = -5 println("負の値設定後の年齢: ${user.age}") }
このヒントを見てもまだ回答を導き出すのが難しいと感じる場合は、先に正解のコードと解説を見て内容を理解するようにしましょう。
解答例
この問題の一つの正解例とそのコードの解説を以下に示します。
正解コードの例
例えば以下のようなプログラムが考えられます。
********************
// ユーザークラスの定義 class User { // プロパティ 'name' の定義とカスタムゲッターおよびセッター var name: String = "名無し" get() { // ゲッター:現在の名前を返す return field } set(value) { // セッター:新しい名前を設定するが、空の場合は「名無し」に設定 field = if (value.isEmpty()) "名無し" else value } // プロパティ 'age' の定義とカスタムゲッターおよびセッター var age: Int = 0 get() { // ゲッター:現在の年齢を返す return field } set(value) { // セッター:新しい年齢を設定するが、負の場合は0に設定 field = if (value < 0) 0 else value } } // メイン関数 fun main() { // Userクラスのインスタンスを作成 val user = User() // 初期の名前と年齢を表示 println("初期の名前: ${user.name}") println("初期の年齢: ${user.age}") // 名前と年齢を更新 user.name = "太郎" user.age = 25 // 更新後の名前と年齢を表示 println("更新後の名前: ${user.name}") println("更新後の年齢: ${user.age}") // 名前を空文字にして設定 user.name = "" println("空文字設定後の名前: ${user.name}") // 年齢を負の値にして設定 user.age = -5 println("負の値設定後の年齢: ${user.age}") }
********************
正解コードの解説
この解説では、Kotlinのコードがどのように動作するのかを順を追って説明し、特に「ゲッター」と「セッター」の部分に注目します。
1. Userクラスの定義
まず、ユーザー情報を管理するためのUser
クラスを定義します。
class User { // プロパティ 'name' の定義とカスタムゲッターおよびセッター var name: String = "名無し" get() { // ゲッター:現在の名前を返す return field } set(value) { // セッター:新しい名前を設定するが、空の場合は「名無し」に設定 field = if (value.isEmpty()) "名無し" else value } // プロパティ 'age' の定義とカスタムゲッターおよびセッター var age: Int = 0 get() { // ゲッター:現在の年齢を返す return field } set(value) { // セッター:新しい年齢を設定するが、負の場合は0に設定 field = if (value < 0) 0 else value } }
プロパティ name
のカスタムゲッターとセッター
- ゲッター
get() { // ゲッター:現在の名前を返す return field }
name
プロパティのゲッターは、現在のname
の値を返します。この値は内部プロパティfield
に格納されています。
- セッター
set(value) { // セッター:新しい名前を設定するが、空の場合は「名無し」に設定 field = if (value.isEmpty()) "名無し" else value }
name
プロパティのセッターは、新しい値をname
に設定しますが、空文字が設定された場合はデフォルト値の「名無し」を設定します。
プロパティ age
のカスタムゲッターとセッター
- ゲッター
get() { // ゲッター:現在の年齢を返す return field }
age
プロパティのゲッターは、現在のage
の値を返します。
- セッター
set(value) { // セッター:新しい年齢を設定するが、負の場合は0に設定 field = if (value < 0) 0 else value }
age
プロパティのセッターは、新しい値をage
に設定しますが、負の値が設定された場合は0を設定します。
2. メイン関数
メイン関数でユーザー情報を操作します。
fun main() { // Userクラスのインスタンスを作成 val user = User() // 初期の名前と年齢を表示 println("初期の名前: ${user.name}") println("初期の年齢: ${user.age}") // 名前と年齢を更新 user.name = "太郎" user.age = 25 // 更新後の名前と年齢を表示 println("更新後の名前: ${user.name}") println("更新後の年齢: ${user.age}") // 名前を空文字にして設定 user.name = "" println("空文字設定後の名前: ${user.name}") // 年齢を負の値にして設定 user.age = -5 println("負の値設定後の年齢: ${user.age}") }
初期の名前と年齢を表示
println("初期の名前: ${user.name}") println("初期の年齢: ${user.age}")
ここでは、User
クラスのインスタンスuser
を作成し、初期状態のname
とage
を表示します。
名前と年齢を更新
user.name = "太郎" user.age = 25
ここでは、name
とage
を新しい値に更新します。セッターが適用され、適切なバリデーションが行われます。
更新後の名前と年齢を表示
println("更新後の名前: ${user.name}") println("更新後の年齢: ${user.age}")
更新後のname
とage
を表示します。
名前を空文字に設定し結果を表示
user.name = "" println("空文字設定後の名前: ${user.name}")
名前を空文字に設定すると、セッターにより「名無し」が設定されます。
年齢を負の値に設定し結果を表示
user.age = -5 println("負の値設定後の年齢: ${user.age}")
年齢を負の値に設定すると、セッターにより0が設定されます。
このように、ゲッターとセッターを活用することでプロパティの値を適切に管理し、データの整合性を保つことができます。
<<前の問題 |
問題集Top |
次の問題>> |
この問題への質問・コメント
この問題を作成するにあたりAIを活用しています。
問題ないことは確認していますが、もし間違いや表現の違和感などありましたら、ご指摘頂けると大変助かります。