第二章.コートリンきそ
2.1基本要素:関数と変数
2.1.1 Hello, World !
fun main(args: Array<String>) {
println("Hello, world!")
}
fun main(args: Array<String>) {
println("Hello, world!")
}
2.1.2関数
✅ 文と式の区別
逆に,代入文はJavaでは式であり,コトリンでは文(statement)である.
関数#カンスウ#
// 블록이 본문인 함수
fun maxEx1(a: Int, b: Int) : Int {
return if (a > b) a else b
}
// 식이 본문인 함수
fun maxEx2(a: Int, b:Int) : Int = if (a>b) a else b
// 반환 타입을 생략한 함수
fun maxEx3(a: Int, b:Int) = if (a>b) a else b
ブロックが本文の関数:本文が括弧の関数
数式が本文の関数:等号と数式からなる関数
なぜ戻りタイプを省略できるのか(式が本明細書の関数の戻りタイプであることを省略するしかない)
コトリンは静的タイプ化言語であり、コンパイル時にすべてのタイプを指定する必要があります.ただし、式が本文の関数の場合、コンパイラは戻りタイプを書く必要はありません.関数の本文を分析することで、結果タイプを関数戻りタイプとして決定します.→類型推定が可能です.
2.1.3変数
// 타입 생략
val answer = 42
// 타입 명시
val answer: Int = 42
可変変数と非可変変数
デフォルトでは、すべての変数がval、不変変数として宣言され、必要に応じてvarに変更することを推奨します.
可変参照オブジェクトと可変オブジェクトを割り当て効果のない関数と組み合わせて使用すると、コードは関数型コードに近づきます.
val languages = arrayListOf("Java") // 불변 참조를 선언
languages.add("Kotlin") // 참조가 가리키는 객체 내부 변경
// Error : type mismach 발생 - 컴파일 오류
var answer = 123;
answer = "hello world"
2.1.4文字列のより簡単なフォーマット:文字列テンプレート
// 문자열 템플릿 사용
fun main(args: Array<String>) {
val name = if(args.size > 0) args[0] else "Kotlin"
println("Hello, $name!")
if(args.size > 0){
println("Bye, ${args[0]}") // args 배열의 원소를 넣기 위해${} 구문 사용
}
println("\$") // 달려 표시 ($)를 쓸 경우에는 이스케이프(\) 사용
}
コトリンはjavaと同様に変数名にもハングルを含めることができます.(すべてのUnicode文字に変数名がある)
文字列テンプレートに
$name님, 반가워요
のように「$変数名」とハングルを付けると、コンパイルエラーが発生します.これは、コートリンコンパイラが英語と韓国語を識別子として同時に使用しているためです.→
${name}님, 반가워요
変数名を{}で包み、普段は牛で包むのが可読性に良い.2.2クラスとproperty // Java Person 클래스
public class Person {
private final String name;
public String getName() {
return name;
}
public Person(String name) {
this.name = name;
}
}
Javaの場合、フィールドが長いほど、コンストラクション関数のパラメータ数が多くなります.つまり,増加を繰り返すコードが増える.// 코틀린으로 변환한 Person 클래스
class Person (val name : String)
// Java Person 클래스
public class Person {
private final String name;
public String getName() {
return name;
}
public Person(String name) {
this.name = name;
}
}
// 코틀린으로 변환한 Person 클래스
class Person (val name : String)
2.2.1契約
Javaは、フィールドとアクセス者を一緒に置くことをPropertyと呼びます.コトリンプロトコルはJavaのフィールドとアクセス者メソッドに完全に取って代わった.
class Person(
val name: String, // private 변수, 읽기 전용, 단순한 공개 getter만 만들어낸다.
var isMarried: Boolean // private 변수, 공개 getter, 공개 setter 만들어낸다.
)
val person = Person("Bob", true) // new 키워드 사용 안하고 생성자 호출
// 프로퍼티 이름을 직접 사용해도 코틀린이 자동으로 getter 호출
println(person.name)
println(person.isMarried)
2.2.2カスタム訪問者
class Rectangle(val height: Int, val width: Int) {
val isSquare: Boolean
get() {
return height == width
}
// get() = height == width
}
isSquare Propertyは自己実現を提供するgetterを有するクライアントがpropertyにアクセスすると、get()に対応する論理を使用してproperty値が毎回再計算されます.
パラメータのない関数を定義する方法と、Customgetterを定義する方法は、実装とパフォーマンスに違いはありません.
2.2.3スペルミスソース構造:ディレクトリとパッケージ
すべてのスペルミスファイルの一番前にpackage文を置くことができます.
同じパッケージに属している場合は、他のファイルで定義された宣言として直接使用できます.
逆に、他のパッケージで定義した宣言を使用するには、import宣言を使用します.
// 클래스와 함수 선언을 패키지에 넣기
package geometry.shapes
import java.util.*
class Rectangle(val height: Int, val width: Int) {
val isSquare: Boolean
get() = height == width
}
fun createRandomRectangle(): Rectangle {
val random = Random()
return Rectangle(random.nextInt(), random.nextInt())
}
// 다른 패키지에 있는 함수 임포트하기
package geometry.shapes.createRandomRectangle
fun main(args: Array<String>) {
println(createRandomRectangle().isSquare)
}
Javaと同様に、パッケージごとにディレクトリを整理することが望ましい.特にjavaとcortlinを同時に使用するプロジェクトではjava方式に従うことが重要である.2.3式と処理の選択:enumとwhen
2.3.1クラス定義
// 간단한 enum 클래스
enum class Color {
RED, ORANGE, YELLOW, GREEN, INDIGO, VIOLET
}
Java宣言はenum
、コートリン宣言はenum class
// 프로퍼티와 메소드가 있는 enum 클래스
enum class Color(val r: Int, val g: Int, val b: Int) // 상수 프로퍼티 정의
{
RED(255, 0, 0),
ORANGE(255, 165, 0),
YELLOW(255, 255, 0),
GREEN(0, 255, 0),
BLUE(0, 0, 255),
INDIGO(75, 0, 130),
VIOLET(238, 130, 238); // 반드시 세미콜론으로 종료
fun rgb() = (r * 256 + g) * 256 + b // enum 클래스 안에 메소드 정의
}
fun main() {
println(Color.BLUE.rgb())
}
2.3.2 whenを使用してenumクラスを処理する
fun getMnemonic(color: Color) =
when (color) { // 함수 반환 값으로 when 식을 사용
Color.RED -> "Rechard"
Color.ORANGE -> "Of"
Color.YELLOW -> "York"
Color.GREEN -> "Grave"
Color.BLUE -> "Battle"
Color.INDIGO -> "In"
Color.VIOLET -> "Vain"
}
fun getWarmth(color: Color) = when (color) {
Color.RED, Color.ORANGE, Color.YELLOW -> "warm"
Color.GREEN -> "neutral"
Color.BLUE, Color.INDIGO, Color.VIOLET -> "cold"
}
fun main() {
println(getMnemonic(Color.BLUE))
println(getWarmth(Color.ORANGE))
}
Javaと異なり、四半期ごとの末尾にブレークポイントを入れる必要はありません.
1四半期に複数の値を組み合わせモードとして使用する場合は、カンマ(,)で区切ります.
enum定数値をインポートすることで、enumクラス修飾子なしでenumを使用できます.import ch2.Color.*
fun getMnemonic(color: Color) = when (color) {
RED -> "Rechard"
ORANGE -> "Of"
YELLOW -> "York"
GREEN -> "Grave"
BLUE -> "Battle"
INDIGO -> "In"
VIOLET -> "Vain"
}
2.3.3 whenを任意のオブジェクトと一緒に使用する
Javaのswtich
とは異なり、コトリンwhen
の分岐条件は任意のオブジェクトを許可する.fun mix(c1: Color, c2: Color) =
// when 식의 인자로 아무 객체나 사용 가능, when은 받은 인자 객체가 각 분기 조건에 있는 객체와 같은지 테스트
when (setOf(c1, c2)) {
setOf(RED, YELLOW) -> ORANGE
setOf(YELLOW, BLUE) -> GREEN
setOf(BLUE, VIOLET) -> INDIGO
// 매치되는 분기 조건이 없으면 이 문장 실행
else -> throw Exception("Dirty color")
}
// 간단한 enum 클래스
enum class Color {
RED, ORANGE, YELLOW, GREEN, INDIGO, VIOLET
}
// 프로퍼티와 메소드가 있는 enum 클래스
enum class Color(val r: Int, val g: Int, val b: Int) // 상수 프로퍼티 정의
{
RED(255, 0, 0),
ORANGE(255, 165, 0),
YELLOW(255, 255, 0),
GREEN(0, 255, 0),
BLUE(0, 0, 255),
INDIGO(75, 0, 130),
VIOLET(238, 130, 238); // 반드시 세미콜론으로 종료
fun rgb() = (r * 256 + g) * 256 + b // enum 클래스 안에 메소드 정의
}
fun main() {
println(Color.BLUE.rgb())
}
fun getMnemonic(color: Color) =
when (color) { // 함수 반환 값으로 when 식을 사용
Color.RED -> "Rechard"
Color.ORANGE -> "Of"
Color.YELLOW -> "York"
Color.GREEN -> "Grave"
Color.BLUE -> "Battle"
Color.INDIGO -> "In"
Color.VIOLET -> "Vain"
}
fun getWarmth(color: Color) = when (color) {
Color.RED, Color.ORANGE, Color.YELLOW -> "warm"
Color.GREEN -> "neutral"
Color.BLUE, Color.INDIGO, Color.VIOLET -> "cold"
}
fun main() {
println(getMnemonic(Color.BLUE))
println(getWarmth(Color.ORANGE))
}
import ch2.Color.*
fun getMnemonic(color: Color) = when (color) {
RED -> "Rechard"
ORANGE -> "Of"
YELLOW -> "York"
GREEN -> "Grave"
BLUE -> "Battle"
INDIGO -> "In"
VIOLET -> "Vain"
}
fun mix(c1: Color, c2: Color) =
// when 식의 인자로 아무 객체나 사용 가능, when은 받은 인자 객체가 각 분기 조건에 있는 객체와 같은지 테스트
when (setOf(c1, c2)) {
setOf(RED, YELLOW) -> ORANGE
setOf(YELLOW, BLUE) -> GREEN
setOf(BLUE, VIOLET) -> INDIGO
// 매치되는 분기 조건이 없으면 이 문장 실행
else -> throw Exception("Dirty color")
}
2.3.4使用時パラメータなし
ある時点でパラメータがない場合は、各ブランチの条件が達成した結果を計算する必要があります.
fun mixOptimized(c1: Color, c2: Color) =
// when 에 아무 인자가 없다.
when {
(c1 == RED && c2 == YELLOW) ||
(c1 == YELLOW && c2 == RED) -> ORANGE
(c1 == YELLOW && c2 == BLUE) ||
(c1 == BLUE && c2 == YELLOW) -> GREEN
(c1 == BLUE && c2 == VIOLET) ||
(c1 == VIOLET && c2 == BLUE) -> INDIGO
else -> throw Exception("Dirty color")
}
2.3.5インテリジェント鋳造:タイプ検査とタイプ鋳造を組み合わせて
( 1 + 2 ) + 4
のような算術式を計算する関数を構築しましょう.// 식을 위한 인터페이스
interface Expr
// value라는 프로퍼티만 존재하는 단순한 클래스, Expr 인터페이스를 구현
class Num(val value: Int) : Expr
// Expr 타입의 객체라면 Sum 연산의 인자가 될 수 있다.
// 따라서, Num이나 다른 Sum이 Sum의 인자로 올 수 있다.
class Sum(val left: Expr, val right: Expr) : Expr
// Java 스타일
// if 사용해서 식 계산
fun eval(e: Expr): Int {
if (e is Num) {
val n = e as Num
return n.value
}
if (e is Sum) {
// 변수 e 에 대해 스마트 캐스트를 사용한다.
return eval(e.right) + eval(e.left)
}
throw IllegalArgumentException("Unkown expression")
}
Expr暗黙インタフェースSum,NumクラスはExprインタフェースを実現するクラスである
is
を使用して変数タイプをチェックします(Javaのinstanceof
と同様).instanceof
と決定され、このタイプのメンバーにアクセスするために開発者はタイプis
で検査を行った後、本当ならコンパイラは自分で選びます.→ Smart Cast is
によって変数の値タイプを検査する、その値が変更できない場合にのみ動作as
キーワード→val n = e as Num
を使用した明示的な鋳造2.3.6再包装:ifをいつに変更するか
コトリンのif戻り式→値.価値を創造する.→したがって、Javaとは異なり、他に3つの演算子はありません.
Javaのifは文→値を返さない.
// 값을 만들어내는 if 식
fun eval(e: Expr): Int =
if (e is Num) {
e.value
} else if (e is Sum) {
eval(e.right) + eval(e.left)
} else {
throw IllegalArgumentException("Unkown expression")
}
// if 중첩 대신 when 사용하기
fun eval(e: Expr): Int =
when (e) {
is Num -> e.value // 인자 타입을 검사하는 when 분기에서 스마트 캐스트 됨
is Sum -> eval(e.left) + eval(e.right)
else -> throw IllegalArgumentException("Unkown expression")
}
2.3.7 ifブランチとwhenブランチでのブロックの使用
ifまたはwhenは、ブランチでブロック→ブロックの最後の文を有効にすると、ブロック全体の結果になります.
fun evalWithLogging(e: Expr): Int =
when (e) {
is Num -> {
println("num: ${e.value}")
e.value // 블록의 마지막 식이므로 e.value가 반환된다.
}
is Sum -> {
val left = evalWithLogging(e.left)
val right = evalWithLogging(e.right)
println("sum: $left + $right")
left + right
}
else -> throw IllegalArgumentException("Unkown expression")
}
2.4ターゲット・イテレーション:whileとfor rough
2.4.1同時循環
// 조건이 참인 동안 본문 반복 실행
while(조건) {
/*....*/
}
// 맨 처음 무조건 본문 한번 실행 후, 조건이 참인 동안 본문 반복 실행
do{
/*....*/
} while(조건)
2.4.2カウントのイテレーション:範囲とカウント
コトリンにはjava forループに対応する要素はありません.
val oneToTen = 1..10 // 양 끝 구간 포함, 1 ~ 10
fun fizzbuxx(i: Int) =
when {
i % 15 == 0 -> "FizzBuzz "
i % 3 == 0 -> "Fizz "
i % 5 == 0 -> "Buzz "
else -> "$i "
}
for (i in 1..100) {
println(fizzbuxx(i))
}
for (i in 100 downTo 1 step 2){
print(fizzbuxx(i))
}
step
:増分downTo
:反転..
:常に範囲の末尾を含むuntil
:終了値を含まない→for(x in 0 until size)
またはfor (x in 0 .. size-1)
2.4.3マッピングされたイテレーション
// A ~ F 까지 문자 범위 이터레이션
for(c in 'A'..'F'){
// 아스키 코드를 2진 표현으로 변경
val binary = Integer.toBinaryString(c.toInt())
// c를 키로 c의 2진 표현을 맵에 넣는다.
binaryReps[c] = binary // 자바의 map put 과 유사: binaryReps.put(c, binary)
}
// 맵에 대한 이터레이션, 맵의 Key와 Value를 두 변수에 대입
for((letter, binary) in binaryReps) {
println("$letter = $binary")
}
val list = arrayListOf("10", "11", "1001")
// 인덱스와 함께 컬렉션을 이터레이션 한다.
for ((idx, element) in list.withIndex()){
println("$idx: $element")
}
2.4.4 inローカルセットまたは範囲内の要素をチェックする
in演算子:範囲に属する値を決定する
!in演算子:範囲外の値を決定する
fun isLetter(c: Char) = c in 'a'..'z' || c in 'A'..'Z'
fun isNotDigit(c: Char) = c !in '0'..'9'
println(isLetter('q')) // true
println(isNotDigit('x')) // true
fun recognize(c: Char) = when (c) {
in '0'..'9' -> "It's a digit!"
in 'a'..'z', in 'A'..'Z' -> "It's a letter!"
else -> "I don't know"
}
println(recognize('8')) // It's a digit!
比較可能クラス(java.lang.Compabiledインタフェースを実装するクラス)の場合、クラスのインスタンスオブジェクトを使用して範囲を作成できます.2.5エラー処理異常
コトリンのデフォルトの例外処理構文はJavaに似ています
例外インスタンスを作成するときにnewキーを追加する必要はありません.
Javaとは異なり、コトリンのthrowは式であり、異なる方法で含むことができる.
val percentage =
if (number in 0..100)
number
else
// throw는 식이다. -> 값을 만들어낸다.
throw IllegalArgumentException("A percentage value must be between 0 and 100: $number")
2.5.1 try, catch, finally
fun readNumber(reader: BufferedReader): Int? {
try {
val line = reader.readLine()
return Integer.parseInt(line)
} catch (e: NumberFormatException) {
return null
} finally {
reader.close()
}
}
Javaコードとの最大の違いはthrowsセクションにコードがないことです2.5.2. tryで使用
コトリンのtryキーワードは式です.→値切る.
したがって、tryの値を変数に代入することができます.tryはifとは異なり、カッコ{}で囲まなければなりません.
fun readNumber(reader: BufferedReader) {
// 예외가 발생하지 않으면, 이 값을 사용
val number = try {
Integer.parseInt(reader.readLine())
} catch (e: NumberFormatException) {
// return //catch 블록 다음 코드는 실행 되지 않음
null // 예외가 발생하면 null값을 사용
}
println(number)
}
出典:(書籍)Kotlin Action DemitrizeMerof, ストラナイサコワ 作者の紹介Reference
この問題について(第二章.コートリンきそ), 我々は、より多くの情報をここで見つけました https://velog.io/@dev_jhjhj/2장.-코틀린-기초テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol