// Hello Worldを出力する最小限のコード
/*
fun main(){
print("Hello World!")
}
*/
// 実行は shift+ cntrol + F10
// コメント文 一行
/* コメント文 複数行
コメント
コメント
*/
/* 変数の定義
val 再代入不可
var 再代入可能
*/
/* 型
String
Char
Int
Short
Long
Float
Double
boolean : true or false
型を付けない場合でも型推論が機能する
*/
// タブtab : \t
// 改行new line : \n
// 演算 + - * / %
// カウントアップ カウントダウン ++ --
// 代入
// z = z + 5
// z += 5
// 論理演算子 and or not
// && || !
fun main(){
val s: String = " This is string"
val c: Char = 'a'
val i: Int = 100
val f: Float = 123.456f
val b: Boolean = false
println("$s $c $i $f $b")
println("$s \t $c \n $i \t $f \n $b \n")
val x = 10 // 型推論を使用
println(x + 3)
println(x - 3)
println(x * 3)
println(x / 3)
println(x / 3.0)
println(x % 3)
var y = 10
println(y++)
println(y--)
var z = 10
z = z + 10
println(z)
z += 10
println(z)
val flag= true
println(!flag)
println(flag || !flag)
println(flag && !flag)
// 文字と数値の連結
println("hello" + " world")
val name = "Mike"
println("My name is $name") // My name is Mike
val my_age = 20
val your_age = 30
println("私とあなたの年齢を足し算すると ${my_age + your_age} 歳です。")
// if文
// 比較演算子 == > >= < <= !=
val score = 55
if (score > 70) {
println("あなたはのスコアは $score です。 合格")
}else if (score > 50) {
println("あたはのスコアは $score です。不合格です。")
}else{
println("もう一度 学習し直しましょう。")
}
// if文の結果を代入できる
val result = if (score > 80) "合格" else "不合格"
println(result)
// when文 : 他の言語ではswitch文に相当する
val dice = 4
when (dice){
1, 2 -> println("1点")
3, 4 -> println("3点")
5, 6 -> println("5点")
in 7..10 -> println(" No way !")
else -> println("終了")
}
// whe文の結果を代入できる
val point = when(dice){
1, 2 -> "1点"
3, 4 -> "3点"
5, 6 -> "5点"
else -> "終了"
}
println(point)
// while文
var cnt = 0 // 初期化
while ( cnt < 10){
print("while loop : $cnt \n")
cnt++
}
// do while文 :後判定なので必ず1回は実行される。
cnt = 0 //初期化
do {
println("do_while loop : $cnt")
cnt++
}while (cnt < 10)
// for文 と if文 continue , break の組み合わせ
for (j in 0..10){
if (j == 3){
continue // for文を強制的に次へすすめる・
}
if (j == 8){
break // for文を抜ける
}
println(j)
}
// 自分で定義した関数を実行する
sayHello()
sayHelloNameAge("Mike", 20)
sayHelloNameAge()
val msg = sayHelloReturn()
println(msg)
val msg_shorty = sayHelloReturnShorty()
println(msg_shorty)
// クラスのインスタンスを作成してメソドを実行する
val user = User() // クラスUserのインスタンスuserが作成された
user.sayName() // メソドを実行
user.name = "DJ" // プロパティを書き換えてみる
user.sayName() // 書き換わっているか確認
// クラスのインスタンスをコンストラクター引数付きで作成し実行する
val user2 = User2("Tony") //コンスとトラクター引数"Tony"
println(user2.sayName()) //メソドを実行
// 初期化メソドのあるクラスのインスタンスを作成する。(実行なし)
val user3 = User3("Kate")
// getter() , setter() の動きを確認する
val user4 = User4("aaa")
println(user4.team) // getterによって大文字になる BLUE
user4.team = "green" // setterによってプロパティが変更される
println(user4.team) // GREEN
user4.team = "" // 空を入れるとsetterは何もしない。
println(user4.team) // GREEN
// スーパークラスを実行する
val superclass = SuperClass("Bob")
println(superclass.sayGood()) // Good! Bob
// スーパークラスを継承したアドミンクラスを実行する
val adminclass = AdminClass("Baba")
println(adminclass.sayBad()) // Bad !! Baba
println(adminclass.sayGood()) // Good! as the override method
// クラスの拡張
val NonOpenClass_Ext = NonOpenClass("Sam")
println(NonOpenClass_Ext.sayGJ()) // GJ ! Sam
println(NonOpenClass_Ext.sayGoodJob()) // [Ext] Good Job ! Sam
println(NonOpenClass_Ext.myName) // [Ext] I am Sam on getter
// 抽象クラスから作成した具象クラスの動作を確認する
val american = American()
val japanese = Japanese()
american.sayAbst() // Hello
japanese.sayAbst() // こんにちは
// インターフェースを継承したクラスを実行してみる
val user5 = User5()
user5.share() // Sharing...
user5.getInfo() // Share interface version is 1.1 .
// ジェネリクスを使用しない普通のクラスを実行してみる
val myinteger = MyInteger()
myinteger.getThree(100)
// ジェネリクスを使用したクラスを実行してみる <型指定>に注目
val mydata1 = MyData<Int>()
mydata1.getThree(200)
val mydata2 = MyData<String>()
mydata2.getThree("AAA")
// data class を使ってみる
// まずは使用しない場合
val p1 = Point(3,5)
val p2 = Point(3,5)
println(p1) // Point@16c0663d
println(if (p1 == p2 ) "same" else "different") // different
// 値ではなくて、インスタンス番号が渡されているだけ。
// data classを使えば値を渡せる
val p3 = Point2(3,5)
val p4 = Point2(3,5)
println(p3) // Point2(x=3, y=5)
println(if (p3 == p4 ) "same" else "different") // same
// 少し脱線して、コピーメソド、分解宣言
val p4_copy = p4.copy()
val (p4_x, p4_y) = p4
println(p4_copy) // Point2(x=3, y=5)
println("$p4_x : $p4_y") // 3 : 5
// Listを使ってみる
CollectionList()
// Setを使ってみる
CollectionSet()
// Mapを使ってみる
CollectionMap()
// .map .filter .forEach を使ってみる
MapFilterForeach()
// 例外処理
// division(10, 0)
// ↑ エラーがでるException in thread "main" java.lang.ArithmeticException: / by zero
// 命令文をtry{}の中に入れるて 例外処理をcatchに入れる
division(10, 0) // / catch内が実行されました by zero
// 自分で定義した例外処理を実行する
division2(10, -10) // Minus number is not acceptable!
// nullを使ってみる
nullTest()
}
//============================================================
//---- End of main function ----
//============================================================
// 関数を定義する
fun sayHello(){
println("Hello!")
}
// 引数 初期値を定義した関数
fun sayHelloNameAge(name:String = "john", age: Int = 10){ //引数は型宣言が必要
println("Hello $name . I am $age years-old.")
}
// 返り値がある関数を定義する
fun sayHelloReturn(): String { // returnする値の型宣言が必要
return "Hello! as return"
}
// 返り値しかない関数は省略して書くことができる : 型が自明なので宣言不要
fun sayHelloReturnShorty() = "Hello! as return on shorty code"
// クラスを定義する
// クラスのメンバー
// data: プロパティ
// fun : メソド
class User {
// プロパティを定義する
var name = "Me"
// メソドを定義する
fun sayName() {
// println("My name is ${this.name}") // nameは自明なのでthis.は無くても良い
println("My name is $name")
}
}
// コンストラクター引数のあるクラスを定義する
class User2(var name: String) { // () はコンストラクタ引数。ない場合は()も不要
// プロパティを定義する
// var name = "Me" // コンストラクタ引数がある場合は この行は不要
// メソドを定義する
fun sayName() {
// println("My name is ${this.name}") // nameは自明なのでthis.は無くても良い
println("My name is $name")
}
}
// 初期化メソドのあるクラスを定義する
class User3(var name: String) {
//初期化メソドを定義する
init{
println("クラスのインスタンスを作成し、初期化メソドが実行されました。")
}
}
// Kotlinではgetterとsetterによってプロパティを呼び出されている。
// クラス内で定義したvar変数はgetter, setterを書かなくても自動的に返していた。
// 今回はgetterとsetterをちゃんと定義してみる。(追加機能として大文字で返すようにした。)
class User4(var name: String) {
var team = "blue" // ここで宣言すると自動的にgetterとsetterが定義されていた。
// getter : 大文字にして返すようにする。
get(){
// get()内で変数はfieldと表現される。(特殊)
return field.toUpperCase()
}
// setter 慣習的に引数はvalueと書く
set(value){
//空文字でない場合だけ機能させること
if (value != ""){
// getterと同様に var変数はfieldと表現される。
field = value
}
}
// メソドを定義する
fun sayName() {
println("My name is $name")
}
}
// クラスの継承 : 元クラスの機能を拡張して新しいクラスを作成する
// SuperClass : 親クラス(元となるクラス)
// AdminClass : 子クラス(機能を追加したクラス)
// 上書きするメソドにはoverrideとつけなければならない。
class AdminClass(name: String): SuperClass(name){
fun sayBad(){
println("Bad !! $name")
}
override fun sayGood(){
println("Good! as the override method")
}
}
// 継承しても良い! という意味で子クラスにはopenを頭につけなければならない
// 上書きしても良いメソドにはopenをつけなければならない。
open class SuperClass(var name: String){
open fun sayGood(){
println("Good! $name")
}
}
// アクセス修飾子:アクセスをコントロールする
// public : どこからでもアクセス可能 メインクラス そのクラス サブクラス(子クラス)
// protected : そのクラス + サブクラス
// private : そのクラス
// 例) メインからnemeを使えなくする方法
// open class SuperClass(protedted var name: String){
// 例) そのクラス内でしかnameを使えなくする方法
// open class SuperClass(private var name: String){
// クラスの拡張: クラスを継承したいがsuperClassがopenになっていない時、どうやって機能を追加するか。
// 元クラス
class NonOpenClass(var name: String){
fun sayGJ() {
println("GJ ! $name")
}
}
// メソドを拡張: 機能追加
fun NonOpenClass.sayGoodJob(){
println("[Ext] Good Job ! $name")
}
// プロパティを拡張
val NonOpenClass.myName: String
get() = "[Ext] I am $name on getter"
// メソドの上書き(実験) = だめ、元クラスが優先される。
fun NonOpenClass.sayGJ(){
println("[Ext] GJ ! $name")
}
// 抽象クラス:他のクラスに継承してもらう前提で作られるクラス
// 具象クラス:抽象クラスを継承する新しいクラス
// 使い方:開発規模が大きいとき、具象クラスの共通メソドを
// 一旦抽象クラスのメソドとしてまとめておいて、
// 実装は具象クラスに任せるということをする。
// 抽象クラス
abstract class AbstClass{
abstract fun sayAbst()
}
// 具象クラス1
class Japanese: AbstClass(){
override fun sayAbst() {
println("こんにちは")
}
}
// 具象クラス2
class American: AbstClass(){
override fun sayAbst() {
println("Hello")
}
}
// Interface : クラスの機能を拡張する
// interfaceの中では抽象プロパティ、抽象メソドでもabstractを書く必要がない。
// 継承と違って、クラスにいくつでも実装できる。
interface Sharable{
//抽象プロパティ
val version: Double //具象クラスで実装するので、ここでは型だけを定義すれば良い
//抽象メソド
fun share() //具象クラスで実装するので、メソド名だけ定義しておけば良い
//普通のメソド
fun getInfo(){
print("Share interface version is $version .")
}
}
// Interfaceを継承する
class User5: Sharable{
override val version = 1.1
override fun share() {
println("Sharing...")
}
}
// ジェネリクス
// まずはジェネリクスを使用しない例
class MyInteger{
// プロパティを3回出力するメソド
fun getThree(x: Int){
println(x)
println(x)
println(x)
}
}
// これでは、IntではなくStringを入れたい場合に書き換えなければならない。
// ジェネリクスを使用して型を汎用化できる
class MyData<T>{ // <>内は何でも良いが、慣習的にタイプの意味でTとしている。
// 実行時に具体的なタイプを入れればOK
fun getThree(x: T){ // タイプをコンストラクタと同じTにする。
println(x)
println(x)
println(x)
}
}
// data classを使ってみる
// 使わない場合
class Point(val x: Int, val y: Int){
}
// これではインスタンスに引数が渡されないので
// mainで動かしているp1はインスタンス番号 p1==p2はインスタンスう番号が違う、
// という結果にしかならない。
// data classで解消する
data class Point2(val x: Int, val y: Int){
}
// Collection : データの集合
// List 順番がある配列
// Set 順番がなく重複がない集合
// Map キーとバリューで管理していく集合
// Immutable 変更可能
// Mutable 変更不可
fun CollectionList(){
// listOfは型変更不可Immutable
// 変更したい場合はmutableListOf<>()を使用すること
val li: List<Int> = listOf(1, 2, 3, 4, 5) // 型推定も有効
println(li[3]) // 4
println(li.size) // 5
for (element in li){
println(element) // 1 2 3 4 5
}
}
fun CollectionSet(){
// setOf : 書き換え可能にしたい場合は mutableSet<>()を使用すること
val se: Set<Int> = setOf(1,2,2,2,3) // 重複している2は無視される
println(se) // [1, 2, 3]
// 要素が含まれているか調べる
println(se.contains(3)) // true
// 積集合 和集合 差集合
val se1 = setOf(1,3,5,7)
val se2 = setOf(3,5,8,9)
println(se1.intersect(se2)) // 積集合 [3, 5]
println(se1.union(se2)) // 和集合 [1, 3, 5, 7, 8, 9]
println(se1.subtract(se2)) // 差集合 [1, 7]
}
fun CollectionMap(){
// MapOf : 書き換え可能にしたい場合は mutableMapOf<,>()を使用すること
val users6: Map<String, Int> = mapOf("a" to 10, "b" to 20, "c" to 30)
println(users6) // {a=10, b=20, c=30}
println(users6.size) // 3
println(users6.keys) // [a, b, c]
println(users6.values) // [10, 20, 30]
println(users6.entries) // [a=10, b=20, c=30]
println(users6["b"]) //20
}
// リスト内の要素を操作するmap 抽出するfilter 出力するforeach
fun MapFilterForeach(){
val values = listOf(12.3, 45.6, 78.9)
values
// valuesに10%のVATを追加して出力する
//.map {n -> n * 1.10} // 適当な引数n -> 処理
// itを使うと引数nを省略できる
.map { it * 1.10 }
// filterを使って抽出する
.filter { it > 20 }
// foreachで出力する
.forEach { println(it) }
}
// 例外処理try cahtch : Kotlinに予め設定されている
fun division(a: Int, b: Int){
try {
println(a / b)
} catch (e: ArithmeticException) {// 予めKotlinが用意している例外名
println("catch内が実行されました")
println(e.message) // 予めKotlinが用意している例外プロパティ
}
}
// 独自の例外処理を定義する try if throw catch / Throwable(message)
fun division2(a: Int, b: Int){
try{
// 例外処理を実行する条件
if (b<0) {
// 例外処理を実行する
throw MyException("Minus number is not acceptable!")
}
// catchしたい例外処理を定義して、catchしたときの処理を実行する
} catch (e: MyException) {
println(e.message)
}
}
// Throwableという予めKotlinが用意してあるクラスを継承する.
// コンストラクタ引数として例外プロパティmessageを入れる
class MyException(message: String): Throwable(message)
// Null 安全 : Nullable型を使用してみる
fun nullTest(){
// あるデータがnullかどうか曖昧だと重大なバグが発生する可能性が高い。
// どうしてもnullを使いたい場合は nullableという特殊な型指定 ? が必要
// val s: String = null // これはエラーになる
val s: String? = null
println(s) // ちゃんとnullになった
// nallableな変数は後々 nullかどうかチェックしながら使用すること
if (s != null){ // nullでないときだけ実行する
println(s.length)
}else{
println("Variable is null.") // Variable is null.
}
// もっと簡単にnullチェックして使用する方法
println(s?.length) // nullなので実行されない
// エルビスプレスリー演算子?:を使用して, nullだったら -1を返す
println(s?.length ?: -1) // -1
// nullだったら例外を発生させる
// print(s!!.length) //Exception in thread "main" kotlin.KotlinNullPointerException
}