KotlinではrangeTo()関数を用いることで、簡単に値の範囲を作成することができます。
rangeToの代わりに演算子”..“を用いることもできます。rangeTo()はよくinや!inと共に使われます。
if (i in 1..4) { //iが1から4の間 1 <= i && i <= 4と同じ コンパイラにはi in 1.rangeTo(4)と解釈される
print(i)
}
ちなみに1..4で渡される値はIntRange型という範囲を指定する型になります。
ある値(i)がその範囲内にあるかを確認するにはcontains、またはinという演算子を用います。
上記のコードをcontainsを用いて表現する場合、以下のようになります。
if ((1..4).contains(i)) {
print(i)
}
範囲指定を用いて、ある日付(date)がそれぞれ日付を表すfirstとlastの間(それぞれの値も含む)に含まれているかをチェックする関数を実装してください。
fun checkInRange(date: MyDate, first: MyDate, last: MyDate): Boolean {
return TODO()
}
※MyDateクラスは以下のように定義されているものとします。
//MyDate.kt
data class MyDate(val year: Int, val month: Int, val dayOfMonth: Int) : Comparable<MyDate> {
override fun compareTo(other: MyDate): Int {
if (year != other.year) return year - other.year
if (month != other.month) return month - other.month
return dayOfMonth - other.dayOfMonth
}
}
[expander_maker id=”1″ more=”ヒント” less=”非表示”]
val list = listOf("a", "b")
"a" in list // list.contains("a")と同じ
"a" !in list // !list.contains("a")と同じ
date1..date2 // date1.rangeTo(date2)と同じ
Kotlinでは上記コードのようにinはcontainsに、..はrangeToに対応します。
[/expander_maker] [expander_maker id=”1″ more=”答え” less=”非表示”]fun checkInRange(date: MyDate, first: MyDate, last: MyDate): Boolean {
return date in first..last
}
[解説]
dateがIntRange型のfirst..lastに含まれているかをdate in first..lastでチェックしています。
戻り値はBoolean型です。
[/expander_maker]その他の問題はこちらからどうぞ。
プログラミング学習はどうしても一人だとつまづいてしまう時がきます。調べればわかることも少なくないですが、最初のうちは調べ方もわからないことが多いため、あまり効率的ではありません。
効率的かつ挫折せずにプログラミングを学習したい方はスクールを検討してみるのも一つの手です。
中には無料で通えるスクールや、就職保証をしてくれるスクールなどもあるので、きっとあなたの目的に応じて最適のスクールが見つかります!以下の記事で評判がよく特におすすめのスクールをいくつかピックアップしているので、スクール選びで後悔したくない方は御覧ください!
Kotlinの文法をまず学びたい!という方には以下の書籍がおすすめです。Kotlinは日本語書籍がまだ豊富とは言えない状況ですが、細かく解説されており、Kotlin入門者のかたでもつまずくことなく学習できると思います。
[itemlink post_id=”1743″]実際にアプリを作りながら覚えていきたい!という方には以下もお勧めです。はじめに上の書籍で文法をさらっと学んでから取り組むのがお勧めです。
[itemlink post_id=”1745″]Kotlinでは型に事前に定義されている演算子のセットに対して独自の実装を施すことができます。
これらの演算子には前もって定義された記号(+や*など)があり、優先順位も決まっています。演算子を実装するには、対応する型用の特定の名前をもつメンバ関数、または拡張関数を用意します。
例えばa.unaryMinus()という関数は-aという式に対応しており、以下のコードのようにPoint.unaryMinus()をオーバーロードしておけば、-Pointが実際にはオーバーロードされたPoint.unaryMinus()として機能するようになります。
data class Point(val x: Int, val y: Int)
operator fun Point.unaryMinus() = Point(-x, -y)
val point = Point(10, 20)
fun main() {
println(-point) // "Point(x=-10, y=-20)"
}
それぞれの演算子に対して対応する関数があるので、必要に応じて公式リファレンスで確認してください。
演算子をオーバーロードするにはoperator修飾子を使って対応する関数をマーキングします。
interface IndexedContainer {
operator fun get(index: Int)
}
また演算子のオーバーロードをオーバーライドする際には、operator修飾子を省くことができます。
class OrdersList: IndexedContainer {
override fun get(index: Int) { /*...*/ }
}
MyDateクラスにcompareTo関数を追加し、MyDateクラスを比較できるようにしてください。
date1 < date2がエラー無くコンパイルできるようにしましょう。
data class MyDate(val year: Int, val month: Int, val dayOfMonth: Int) : Comparable<MyDate> {
/* TODO */
}
fun test(date1: MyDate, date2: MyDate) {
// this code should compile:
println(date1 < date2)
}
[expander_maker id=”1″ more=”ヒント” less=”非表示”]
date1 < date2は実際にはコンパイラによって、date1.compareTo(date2) < 0と解釈されます。
ですので、MyDateクラスの中でcompareTo関数をオーバーライドし、MyDateクラスのパラメーターに渡されたInt型のyear、month、dayOfMonthとcompareToに渡されたMyData型のyear、month、dayOfMonthとを比較できるようにしましょう。
[/expander_maker] [expander_maker id=”1″ more=”答え” less=”非表示”]data class MyDate(val year: Int, val month: Int, val dayOfMonth: Int) : Comparable<MyDate> {
override fun compareTo(other: MyDate) = when {
year != other.year -> year - other.year
month != other.month -> month - other.month
else -> dayOfMonth - other.dayOfMonth
}
}
fun test(date1: MyDate, date2: MyDate) {
// this code should compile:
println(date1 < date2)
}
[解説]
when式の中で、yearが異なればyearからother.yearを引いた値を返すようにしています。
yearの値とother.yearの値が同じ場合はmonthを…という形で同様にdayOfMonthまで比較させています。
もしdate1.year < date2.yearであれば、date1.compareTo(date2)で返ってくる値は負(<0)になるので、date1.compareTo(date2) < 0はtrueを返すようになります。従って、date1 < date2もtrueになります。
[/expander_maker]その他の問題はこちらからどうぞ。
プログラミング学習はどうしても一人だとつまづいてしまう時がきます。調べればわかることも少なくないですが、最初のうちは調べ方もわからないことが多いため、あまり効率的ではありません。
効率的かつ挫折せずにプログラミングを学習したい方はスクールを検討してみるのも一つの手です。
中には無料で通えるスクールや、就職保証をしてくれるスクールなどもあるので、きっとあなたの目的に応じて最適のスクールが見つかります!以下の記事で評判がよく特におすすめのスクールをいくつかピックアップしているので、スクール選びで後悔したくない方は御覧ください!
Kotlinの文法をまず学びたい!という方には以下の書籍がおすすめです。Kotlinは日本語書籍がまだ豊富とは言えない状況ですが、細かく解説されており、Kotlin入門者のかたでもつまずくことなく学習できると思います。
[itemlink post_id=”1743″]実際にアプリを作りながら覚えていきたい!という方には以下もお勧めです。はじめに上の書籍で文法をさらっと学んでから取り組むのがお勧めです。
[itemlink post_id=”1745″]拡張関数とは特定の型に独自の関数を追加できる機能です。
拡張関数を宣言するには、関数を追加したい型のあとに .関数名(パラメーター) の形で拡張関数を追加します。例えば、以下はMutableList<Int>という型にswapというリストの中身を入れ替える拡張関数を追加するコードです。ちなみに拡張関数が追加される型(MutableList<Int>)のことをレシーバー型を呼びます。
fun MutableList<Int>.swap(index1: Int, index2: Int) {
val tmp = this[index1] // thisはリストに対応しています。
this[index1] = this[index2]
this[index2] = tmp
}
拡張関数内のthisというキーワードはレシーバーオブジェクト(ドットの前で実際に渡されるレシーバー型のオブジェクト)に対応します。これでどのMutableList<Int>上でもswapという関数が呼び出せるようになりました。
val list = mutableListOf(1, 2, 3)
list.swap(0, 2)
さらに以下のようにMutableListの中身の型を<T>にすれば、どのMutableListに対してもswapを使えるようにできます。Tのことをジェネリック型と呼びます。
fun <T> MutableList<T>.swap(index1: Int, index2: Int) {
val tmp = this[index1] // 'this' corresponds to the list
this[index1] = this[index2]
this[index2] = tmp
}
レシーバー型の式の中でジェネリック型を使えるようにするために、関数名の一番最初でもジェネリック型パラメーターを宣言します。
次のコード中の拡張関数 Int.r()とPair.r()を実装し、IntとPairをデータクラスであるRationalNumber型に変換できるようにしてください。Pairはスタンダードライブラリに定義されているクラスです。ちなみにRationalNumberとは日本語で有理数を意味します。二つの整数を用いて分数で表せる数のことですね。
Pair:
data class Pair<out A, out B>(
val first: A,
val second: B
)
問題コード:
fun Int.r(): RationalNumber = TODO()
fun Pair<Int, Int>.r(): RationalNumber = TODO()
data class RationalNumber(val numerator: Int, val denominator: Int) //numerator:分子 denominator:分母
Kotlin Playgroundでコードの編集・動作確認ができます。
[expander_maker id=”1″ more=”ヒント” less=”非表示”]Int.r()ではRationalNumberのコンストラクタのnumeratorにはレシーバーオブジェクトを、denominatorには1を渡します。
Pair.r()ではnumeratorにはfirst、denominatorにはsecondを渡します。
[/expander_maker] [expander_maker id=”1″ more=”答え” less=”非表示”]fun Int.r(): RationalNumber = RationalNumber(this, 1)
fun Pair<Int, Int>.r(): RationalNumber = RationalNumber(first, second)
data class RationalNumber(val numerator: Int, val denominator: Int)
[解説]
Int.r()のRationalNumber(this, 1)で、thisはレシーバーオブジェクトを意味します。たとえば、
4.r()とした場合、RationalNumber(4, 1)となります。
Pairクラスではパラメーターの最初に渡されたIntをfirst、二つ目をsecondとしているので、RationalNumber型に変換される際にはfirstがnumerator(分子)、secondがdenominator(分母)になります。
[/expander_maker]その他の問題はこちらからどうぞ。
プログラミング学習はどうしても一人だとつまづいてしまう時がきます。調べればわかることも少なくないですが、最初のうちは調べ方もわからないことが多いため、あまり効率的ではありません。
効率的かつ挫折せずにプログラミングを学習したい方はスクールを検討してみるのも一つの手です。
中には無料で通えるスクールや、就職保証をしてくれるスクールなどもあるので、きっとあなたの目的に応じて最適のスクールが見つかります!以下の記事で評判がよく特におすすめのスクールをいくつかピックアップしているので、スクール選びで後悔したくない方は御覧ください!
Kotlinの文法をまず学びたい!という方には以下の書籍がおすすめです。Kotlinは日本語書籍がまだ豊富とは言えない状況ですが、細かく解説されており、Kotlin入門者のかたでもつまずくことなく学習できると思います。
[itemlink post_id=”1743″]実際にアプリを作りながら覚えていきたい!という方には以下もお勧めです。はじめに上の書籍で文法をさらっと学んでから取り組むのがお勧めです。
[itemlink post_id=”1745″]クラスや関数をimportする際、import文の後にas 新しい名前と書き加えることで別の名前を指定することができます。別のライブラリからの似たような名前のクラスや関数を複数個使いたい時など、混乱を避けるのに便利です。
import org.test.Message as testMessage //testMessageはorg.test.Messageを表している
以下のコードのコメント部分を解除し、KotlinパッケージからのRandomをKRandomに、javaパッケージからのRandomをJRandomという名前に変更してコンパイルできるようにしてください。
// import kotlin.random.Random
// import java.util.Random
fun useDifferentRandomClasses(): String {
return "Kotlin random: " +
// KRandom.nextInt(2) +
" Java random:" +
// JRandom().nextInt(2) +
"."
}
Kotlin Playgroundでコードの編集・動作確認ができます。
[expander_maker id=”1″ more=”答え” less=”非表示”]import kotlin.random.Random as KRandom
import java.util.Random as JRandom
fun useDifferentRandomClasses(): String {
return "Kotlin random: " +
KRandom.nextInt(2) +
" Java random:" +
JRandom().nextInt(2) +
"."
}
[解説]
kotlin.random.Random as KRandomとすることによって、useDifferentRandomClasses()内でもKRandomという名前で使用することができるようになっています。
[/expander_maker]その他の問題はこちらからどうぞ。
プログラミング学習はどうしても一人だとつまづいてしまう時がきます。調べればわかることも少なくないですが、最初のうちは調べ方もわからないことが多いため、あまり効率的ではありません。
効率的かつ挫折せずにプログラミングを学習したい方はスクールを検討してみるのも一つの手です。
中には無料で通えるスクールや、就職保証をしてくれるスクールなどもあるので、きっとあなたの目的に応じて最適のスクールが見つかります!以下の記事で評判がよく特におすすめのスクールをいくつかピックアップしているので、スクール選びで後悔したくない方は御覧ください!
Kotlinの文法をまず学びたい!という方には以下の書籍がおすすめです。Kotlinは日本語書籍がまだ豊富とは言えない状況ですが、細かく解説されており、Kotlin入門者のかたでもつまずくことなく学習できると思います。
[itemlink post_id=”1743″]実際にアプリを作りながら覚えていきたい!という方には以下もお勧めです。はじめに上の書籍で文法をさらっと学んでから取り組むのがお勧めです。
[itemlink post_id=”1745″]シールドクラスとは継承をより制御するための制限がなされたクラスです。シールドクラスの全てのサブクラスはコンパイル時に認知されます。シールドクラスがコンパイルされるモジュールの後で別のサブクラスが発生することはありません。つまりシールドクラスが宣言されたファイル内でしかそのシールドクラスは継承できないということです。
例えばサードパーティのクライアントがあなたのシールドクラスを別のファイル上のコードで継承することはできません。したがって、シールドクラスのインスタンスはそのクラスのコンパイル時に存在していたものに限ります。ですので、エラー発生時にも確認する場所が限られているので、効率的です。
シールドクラスは簡単にいうとEnumクラスのようなものですが、若干違いがあります。それらがEnumと比べた際のメリットにもっているのでポイントを追って説明していきます。
その違いの一つはシールドクラスはクラスやオブジェクト宣言をクラス内に内包できるという点です。
シールドクラス内にそのシールドクラスを継承するクラスを宣言することができるため、より細かい状態を表現することができます。
例えばテレビの状態を表すEnumクラスがあったとします。ONとOFFという列挙型を保持しており、テレビがついているか、ついていないかを表現することができます。
しかしついていた場合、映されているチャンネルまで表すことはできません。
シールドクラスではクラスを内包することができるので、”テレビの状態を表すシールドクラス”の中で、それぞれON/OFFの状態を表すクラスを作成しシールドクラスを継承させます。
ONの場合にはチャンネルを引数にとってインスタンスを作ることで、ON時のチャンネルまで表現することができるのです。
ちなみに同ファイル内であれば、シールドクラス内に内包しなくても、それを継承したサブクラスの作成は可能です。
ポイント1でもさらっと述べましたが、Enumと決定的に違うのはインスタンスを作れるという点です。
Enumはシングルトンなので、中身の列挙型を変更することはできません。しかしシールドクラスはインスタンスを作成して使用することができるため、各インスタンスの状態を後から変更することもできます。
上の例に続いて述べれば、テレビのチャンネルをあとから変更するメソッドを用意することで、インスタンス生成時とは別のチャンネルを設定することができるのです。
シールドクラスの一番のメリットはwhen式を利用するときに現れます。はじめに述べたように、シールドクラスの中身はenum同様、宣言時に書いたものに限られているので、全ての可能性はシールドクラスの中身に限られています。従って、通常のwhen式のようにelse文を追加して分岐の中でカバーしきれていない可能性について考慮する必要がありません。シールドクラスを利用したwhen式ではelseを省くことができるのです。
シールドクラスを定義するにはsealed修飾子をクラス名の前につけるだけです。
sealed class Expr
data class Const(val number: Double) : Expr()
data class Sum(val e1: Expr, val e2: Expr) : Expr()
object NotANumber : Expr()
前回のスマートキャストの記事で利用したコード(下に載せてあります)のインターフェースをシールドクラスで置き換えてください。そうすることでwhen式のelseが必要なくなります。
前回のコード:
fun eval(expr: Expr): Int =
when (expr) {
is Num -> TODO()
is Sum -> TODO()
}
interface Expr
class Num(val value: Int) : Expr
class Sum(val left: Expr, val right: Expr) : Expr
[expander_maker id=”1″ more=”答え” less=”非表示”]
fun eval(expr: Expr): Int =
when (expr) {
is Num -> expr.value
is Sum -> eval(expr.left) + eval(expr.right)
}
sealed class Expr
class Num(val value: Int) : Expr()
class Sum(val left: Expr, val right: Expr) : Expr()
[解説]
interface Exprをsealed classとして宣言することで、when式内のelseが無くてもコンパイルエラーが起こらなくなっています。
これはevalの引数として渡されているexprが確実にExprを継承しているNumかSumのインスタンスであることが保証されているためです。
[/expander_maker]その他の問題はこちらからどうぞ。
プログラミング学習はどうしても一人だとつまづいてしまう時がきます。調べればわかることも少なくないですが、最初のうちは調べ方もわからないことが多いため、あまり効率的ではありません。
効率的かつ挫折せずにプログラミングを学習したい方はスクールを検討してみるのも一つの手です。
中には無料で通えるスクールや、就職保証をしてくれるスクールなどもあるので、きっとあなたの目的に応じて最適のスクールが見つかります!以下の記事で評判がよく特におすすめのスクールをいくつかピックアップしているので、スクール選びで後悔したくない方は御覧ください!
Kotlinの文法をまず学びたい!という方には以下の書籍がおすすめです。Kotlinは日本語書籍がまだ豊富とは言えない状況ですが、細かく解説されており、Kotlin入門者のかたでもつまずくことなく学習できると思います。
[itemlink post_id=”1743″]実際にアプリを作りながら覚えていきたい!という方には以下もお勧めです。はじめに上の書籍で文法をさらっと学んでから取り組むのがお勧めです。
[itemlink post_id=”1745″]KolinではJavaのように毎回明示的にキャストをする必要はありません。コンパイラがキャスト前の変数が明らかにキャスト後の変数と一致していると判断できる場合には自動的に安全なキャストが挿入されるようになっています。これをスマートキャストと呼びます。
例えば以下のコードではxは自動的にキャストされます。
fun demo(x: Any) {
if (x is String) {
print(x.length) //xは自動的にStringにキャストされている
}
}
if文の条件文の中でxがStringであることをチェックしており、Stringであればlengthを出力するというコードですが、if文のボディでは条件文がtrue、すなわちxがStringであることが確定しているので、lengthを出す際にわざわざキャストしなくてもいいということです。
逆に以下のようにStringじゃなければreturnさせていれば、その後のreturnされていないコードではxはStringなので、同様にスマートキャストが適用されます。
if (x !is String) return
print(x.length) // xは自動的にStringにキャストされている
スマートキャストはwhen文を使用したコードでも適用されます。
when (x) {
is Int -> print(x + 1)
is String -> print(x.length + 1)
is IntArray -> print(x.sum())
}
when文の一つ目ではIntである場合の処理ですので、xはIntにスマートキャストされ、x+1も問題なく処理されます。以降の文も同様です。
スマートキャストは変数のチェックとその変数が使用されるまでの間に変数の中身が変わっていないということをコンパイラが確認できる場合にのみ有効です。具体的には以下のようなに決められています。
以下のJavaコードをスマートキャストとwhenを使ってKotlinで書き換えてください。
Javaコード:
public int eval(Expr expr) {
if (expr instanceof Num) {
return ((Num) expr).getValue();
}
if (expr instanceof Sum) {
Sum sum = (Sum) expr;
return eval(sum.getLeft()) + eval(sum.getRight());
}
throw new IllegalArgumentException("Unknown expression");
}
Kotlinコード:
fun eval(expr: Expr): Int =
when (expr) {
is Num -> TODO()
is Sum -> TODO()
else -> throw IllegalArgumentException("Unknown expression")
}
interface Expr
class Num(val value: Int) : Expr
class Sum(val left: Expr, val right: Expr) : Expr
Kotlin Playgroundでコードの編集・動作確認ができます。
[expander_maker id=”1″ more=”答え” less=”非表示”]fun eval(expr: Expr): Int =
when (expr) {
is Num -> expr.value
is Sum -> eval(expr.left) + eval(expr.right)
else -> throw IllegalArgumentException("Unknown expression")
}
interface Expr
class Num(val value: Int) : Expr
class Sum(val left: Expr, val right: Expr) : Expr
[/expander_maker]
その他の問題はこちらからどうぞ。
プログラミング学習はどうしても一人だとつまづいてしまう時がきます。調べればわかることも少なくないですが、最初のうちは調べ方もわからないことが多いため、あまり効率的ではありません。
効率的かつ挫折せずにプログラミングを学習したい方はスクールを検討してみるのも一つの手です。
中には無料で通えるスクールや、就職保証をしてくれるスクールなどもあるので、きっとあなたの目的に応じて最適のスクールが見つかります!以下の記事で評判がよく特におすすめのスクールをいくつかピックアップしているので、スクール選びで後悔したくない方は御覧ください!
Kotlinの文法をまず学びたい!という方には以下の書籍がおすすめです。Kotlinは日本語書籍がまだ豊富とは言えない状況ですが、細かく解説されており、Kotlin入門者のかたでもつまずくことなく学習できると思います。
[itemlink post_id=”1743″]実際にアプリを作りながら覚えていきたい!という方には以下もお勧めです。はじめに上の書籍で文法をさらっと学んでから取り組むのがお勧めです。
[itemlink post_id=”1745″]ある特定のデータを保持するためのクラスを作りたいということはよくありますよね。
Kotlinではそういったクラスはデータクラスと呼ばれ、クラス宣言の前にdataとつけることによって、データクラスにすることができます。
data class Car(val type: String, val number: Int)
データクラスにするメリットは一般的にデータを保持しているクラスに対して使われるメソッドが自動で生成されるという点です。自動で生成されるメソッドは以下になります。
以下のJavaコードをKotlinコードに書き換えてください。
Javaコード
public class Person {
private final String name;
private final int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
Kotlinコード
class Person
fun getPeople(): List<Person> {
return listOf(Person("Alice", 29), Person("Bob", 31))
}
fun comparePeople(): Boolean {
val p1 = Person("Alice", 29)
val p2 = Person("Alice", 29)
return p1 == p2 // trueになるようにしてください。
}
Kotlin Playgroundでコードの編集・動作確認ができます。
[expander_maker id=”1″ more=”ヒント” less=”非表示”]Kotlinにおけるクラス宣言の形式は以下のようになります。
class クラス名(パラーメーター){ /*…*/ }
パラメーターの中は(val type :String)など、(名前: 型)の形式で表されます。
例)
class Car(val type: String){}
[/expander_maker]
[expander_maker id=”1″ more=”答え” less=”非表示”]
data class Person(val name: String, val age: Int)
fun getPeople(): List<Person> {
return listOf(Person("Alice", 29), Person("Bob", 31))
}
fun comparePeople(): Boolean {
val p1 = Person("Alice", 29)
val p2 = Person("Alice", 29)
return p1 == p2 // trueになるようにしてください。
}
[解説]
data修飾子をclassの前につけることで、パラメーターの中身が自動でクラスメンバになり、上記で紹介したメソッドも使えるようになっています。
dataを無くすとコンパイルエラーがおこることを確認してください。
[/expander_maker]その他の問題はこちらからどうぞ。
プログラミング学習はどうしても一人だとつまづいてしまう時がきます。調べればわかることも少なくないですが、最初のうちは調べ方もわからないことが多いため、あまり効率的ではありません。
効率的かつ挫折せずにプログラミングを学習したい方はスクールを検討してみるのも一つの手です。
中には無料で通えるスクールや、就職保証をしてくれるスクールなどもあるので、きっとあなたの目的に応じて最適のスクールが見つかります!以下の記事で評判がよく特におすすめのスクールをいくつかピックアップしているので、スクール選びで後悔したくない方は御覧ください!
Kotlinの文法をまず学びたい!という方には以下の書籍がおすすめです。Kotlinは日本語書籍がまだ豊富とは言えない状況ですが、細かく解説されており、Kotlin入門者のかたでもつまずくことなく学習できると思います。
[itemlink post_id=”1743″]実際にアプリを作りながら覚えていきたい!という方には以下もお勧めです。はじめに上の書籍で文法をさらっと学んでから取り組むのがお勧めです。
[itemlink post_id=”1745″]Kotlinにおけるラムダ式の正式な書き方は以下のようになります。
val sum: (Int, Int) -> Int = { x: Int, y: Int -> x + y }
もし上記のラムダ式から全ての必須でないアノテーションを無くすと、以下のようになります。
val sum = { x: Int, y: Int -> x + y }
無くてもコンパイラが理解できる部分は無くすとだいぶスッキリしますね。
コレクションに偶数が含まれているかをチェックするためのラムダ式をany関数に渡してください。
any関数は引数として述語(boolean値を出す式や関数)を取り、その述語を満たす(trueになる)要素が一つでもあれば、true返します。
fun containsEven(collection: Collection<Int>): Boolean =
collection.any { TODO() }
Kotlin Playgroundでコードの編集・動作確認ができます。
[expander_maker id=”1″ more=”答え” less=”非表示”]fun containsEven(collection: Collection<Int>): Boolean =
collection.any {it % 2 == 0}
[解説]
他にも
fun containsEven(collection: Collection<Int>): Boolean =
collection.any {i -> i % 2 == 0}
など書き方はありますが、一つ目が一番シンプルな書き方です。
ラムダ式のパラメータが 1 つだけのときは、i -> の代わりに it というパラメータ名で参照することができます。
[/expander_maker]その他の問題はこちらからどうぞ。
プログラミング学習はどうしても一人だとつまづいてしまう時がきます。調べればわかることも少なくないですが、最初のうちは調べ方もわからないことが多いため、あまり効率的ではありません。
効率的かつ挫折せずにプログラミングを学習したい方はスクールを検討してみるのも一つの手です。
中には無料で通えるスクールや、就職保証をしてくれるスクールなどもあるので、きっとあなたの目的に応じて最適のスクールが見つかります!以下の記事で評判がよく特におすすめのスクールをいくつかピックアップしているので、スクール選びで後悔したくない方は御覧ください!
Kotlinの文法をまず学びたい!という方には以下の書籍がおすすめです。Kotlinは日本語書籍がまだ豊富とは言えない状況ですが、細かく解説されており、Kotlin入門者のかたでもつまずくことなく学習できると思います。
[itemlink post_id=”1743″]実際にアプリを作りながら覚えていきたい!という方には以下もお勧めです。はじめに上の書籍で文法をさらっと学んでから取り組むのがお勧めです。
[itemlink post_id=”1745″]throwという式がKotlinにありますが、エルビス演算子(?:)を使った式の一部などで使われます。
val s = person.name ?: throw IllegalArgumentException("Name required")
throw式の型にはNothing型という特別な型が使われます。この型は特に値を持たず、コードが到達しえない場所を示すために使われます。また、Nothingを使うことで何も返さない関数をマークすることができます。
fun fail(message: String): Nothing {
throw IllegalArgumentException(message)
}
この関数を呼び出す際、コンパイラーにこの関数の呼び出しより先は実行しないということを知らせることができます。
val s = person.name ?: fail("Name required")
println(s) // person.nameがnullだった場合、failが呼び出され、sは出力されない。
また、型推論がされるときにもこの型が見られます。
この型のnull許容型はNothing?ですが、nullしか代入されることはありません。もし型推論の値を初期化するのにnullを使い、他に特定の型を決めるのに使われ得る情報がない場合、コンパイラーはNothing?型であると推測します。
val x = null // xはnothing?型です
val l = listOf(null) // lはList<Nothing?>型です
failWithWrongAge関数の戻り値にNothing型を指定してください。
import java.lang.IllegalArgumentException
fun failWithWrongAge(age: Int?) {
throw IllegalArgumentException("Wrong age: $age")
}
fun checkAge(age: Int?) {
if (age == null || age !in 0..150) failWithWrongAge(age)
println("Congrats! Next year you'll be ${age + 1}.")
}
fun main() {
checkAge(10)
}
Kotlin Playgroundでコードの編集・動作確認ができます。
[expander_maker id=”1″ more=”答え” less=”非表示”]import java.lang.IllegalArgumentException
fun failWithWrongAge(age: Int?): Nothing {
throw IllegalArgumentException("Wrong age: $age")
}
fun checkAge(age: Int?) {
if (age == null || age !in 0..150) failWithWrongAge(age)
println("Congrats! Next year you'll be ${age + 1}.")
}
fun main() {
checkAge(10)
}
[解説]
fun failWithWrongAge(age: Int?): Nothingとすることで戻り値をNothing型に指定しています。
Nothing型がないとcheckAge関数がコンパイルされないということが重要です。コンパイラーはageがnullである場合を考えてしまうためです。
[/expander_maker]その他の問題はこちらからどうぞ。
プログラミング学習はどうしても一人だとつまづいてしまう時がきます。調べればわかることも少なくないですが、最初のうちは調べ方もわからないことが多いため、あまり効率的ではありません。
効率的かつ挫折せずにプログラミングを学習したい方はスクールを検討してみるのも一つの手です。
中には無料で通えるスクールや、就職保証をしてくれるスクールなどもあるので、きっとあなたの目的に応じて最適のスクールが見つかります!以下の記事で評判がよく特におすすめのスクールをいくつかピックアップしているので、スクール選びで後悔したくない方は御覧ください!
Kotlinの文法をまず学びたい!という方には以下の書籍がおすすめです。Kotlinは日本語書籍がまだ豊富とは言えない状況ですが、細かく解説されており、Kotlin入門者のかたでもつまずくことなく学習できると思います。
[itemlink post_id=”1743″]実際にアプリを作りながら覚えていきたい!という方には以下もお勧めです。はじめに上の書籍で文法をさらっと学んでから取り組むのがお勧めです。
[itemlink post_id=”1745″]Kotlinの型システムでは、null参照の危険性を排除することに重点が置かれています。
Javaを含む多くのプログラミング言語における落とし穴の一つが、null参照のメンバにアクセスしようとすることによりnull参照エクセプション、いわゆるヌルポ(NullPointerException)を起こしてしまうことです。
Kotlinの型システムはnullである可能性のある参照(null許容参照)とnullがあり得ない参照(非null許容参照)とを区別します。例えば、通常のString型の変数はnullを持つことはあり得ません。
var a: String = "abc" // 通常の初期化ではデフォルトでnullはあり得ない a = null // コンパイルエラーが起こります
nullを許容するには、String?と書いて、null許容Stringとして宣言する必要があります。
var b: String? = "abc" // nullがありえる
b = null // OK
print(b)
a上(nullがあり得ない)でメソッドを呼び出したり、aのプロパティにアクセスしようとしても、ヌルポが発生しないが保証されているので、以下のようなコードを安全に行うことができます。
val l = a.length
ですが、もし同じようにbのプロパティにアクセスしようとすると、nullセーフではないため、コンパイルエラーが起こります。
val l = b.length // エラー: 変数'b' はnullの可能性がある
しかしbのプロパティにアクセスする必要がある場合もありますよね?そのためにはいくつか方法があります。
第一の方法は、明示的にbがnullであるかをチェックすることで、nullの場合かそうでない場合かで別々の処理を行わせることができます。
val l = if (b != null) b.length else -1
コンパイラーはあなたが行ったnullチェックに関する情報を辿るので、if文の中ではlengthを呼び出すことができるようになるのです。以下のように、より複雑な条件文もありえます。
val b: String? = "Kotlin" if (b != null && b.length > 0) { print("String of length ${b.length}") } else { print("Empty string") }
これはnullチェックのあとでbの状態が変わり得ない状況でのみ機能するということを覚えておいてください。つまりbがnullチェックとbを使用する間に、bの内容が書き換えられないローカル変数であるということを意味します。
そうでないと、nullチェックのあとにbがnullに変わってしまう可能性があり、チェックの意味がなくなってしまうからです。
二つ目の方法は安全呼び出し演算子である ?. を使うことです。
val a = "Kotlin"
val b: String? = null
println(b?.length)
println(a?.length) //不必要な安全呼び出し
これはbがnullでなければb.lengthを返し、そうでなければnullを返します。これで返ってくる式の型はInt?です。
安全な呼び出しはチェーンの中で特に便利です。例えば、ボブ(Bob)という従業員がいて(もしかしたらいないかもしれない)、ある部署(Department)に配属され(されないかもしれない)、そこには部長(Head)がいます(いないかもしれない)。そういった場合での部長の名前を取得するコードは以下のようになります。
bob?.department?.head?.name
上のチェーンではbob、department、headのうち、どれか一つでもnullだった場合はnullを返します。
nullでない値に対してのみ、特定の処理を行わせたい場合は、letと安全呼び出し演算子を併用することで実現できます。
val listWithNulls: List<String?> = listOf("Kotlin", null)
for (item in listWithNulls) {
item?.let { println(it) }
}
上記のコードでは、item?の中身がnullでない場合はそれを出力します。nullの場合は無視されます。ですので、実行結果は”Kotlin”のみが出力されます。
また、安全な呼び出しは代入の左辺に来ることもあります。その場合、左辺(代入される側)にあるチェーン内の一つでもnullであった場合、その代入はスキップされ、右辺の式はそれ以上評価されません。
// もしpersonかperson.departmentがnullの場合、関数getManager()は呼び出されない。
person?.department?.head = managersPool.getManager()
以下のJavaコードを一つのif文だけを使うようにKotlinで書き換えてください。(下のKotlinコードのTODO()を書き換えてください)
Javaコード:
public void sendMessageToClient(
@Nullable Client client,
@Nullable String message,
@NotNull Mailer mailer
) {
if (client == null || message == null) return;
PersonalInfo personalInfo = client.getPersonalInfo();
if (personalInfo == null) return;
String email = personalInfo.getEmail();
if (email == null) return;
mailer.sendMessage(email, message);
}
Kotlinコード:
fun sendMessageToClient(
client: Client?, message: String?, mailer: Mailer
) {
TODO()
}
class Client(val personalInfo: PersonalInfo?)
class PersonalInfo(val email: String?)
interface Mailer {
fun sendMessage(email: String, message: String)
}
Kotlin Playgroundでコードの編集・動作確認ができます。
[expander_maker id=”1″ more=”答え” less=”非表示”]fun sendMessageToClient(
client: Client?, message: String?, mailer: Mailer
) {
val email = client?.personalInfo?.email
if (email != null && message != null) {
mailer.sendMessage(email, message)
}
}
class Client(val personalInfo: PersonalInfo?)
class PersonalInfo(val email: String?)
interface Mailer {
fun sendMessage(email: String, message: String)
}
[解説]
null許容型を使用しているので、Javaのように最初にclientとmessageのnullチェックをする必要はありません。val email = client?.personalInfo?.emailで、clientとpersonalInfoの両方がnullでなければ、emailを代入しています。
その後で、emailとmessageがnullでなければ、sendMessageメソッドに値を渡しています
[/expander_maker]その他の問題はこちらからどうぞ。
プログラミング学習はどうしても一人だとつまづいてしまう時がきます。調べればわかることも少なくないですが、最初のうちは調べ方もわからないことが多いため、あまり効率的ではありません。
効率的かつ挫折せずにプログラミングを学習したい方はスクールを検討してみるのも一つの手です。
中には無料で通えるスクールや、就職保証をしてくれるスクールなどもあるので、きっとあなたの目的に応じて最適のスクールが見つかります!以下の記事で評判がよく特におすすめのスクールをいくつかピックアップしているので、スクール選びで後悔したくない方は御覧ください!
Kotlinの文法をまず学びたい!という方には以下の書籍がおすすめです。Kotlinは日本語書籍がまだ豊富とは言えない状況ですが、細かく解説されており、Kotlin入門者のかたでもつまずくことなく学習できると思います。
[itemlink post_id=”1743″]実際にアプリを作りながら覚えていきたい!という方には以下もお勧めです。はじめに上の書籍で文法をさらっと学んでから取り組むのがお勧めです。
[itemlink post_id=”1745″]