+
+
+
\ No newline at end of file
diff --git a/.idea/kotlin-study.iml b/.idea/kotlin-study.iml
new file mode 100644
index 0000000..d6ebd48
--- /dev/null
+++ b/.idea/kotlin-study.iml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml
new file mode 100644
index 0000000..fdf8d99
--- /dev/null
+++ b/.idea/kotlinc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..e800438
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..aec898a
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/kotlin-baseball/src/main/kotlin/baseball/Application.kt b/kotlin-baseball/src/main/kotlin/baseball/Application.kt
index 148d75c..603d348 100644
--- a/kotlin-baseball/src/main/kotlin/baseball/Application.kt
+++ b/kotlin-baseball/src/main/kotlin/baseball/Application.kt
@@ -1,5 +1,5 @@
package baseball
fun main() {
- TODO("프로그램 구현")
+ print("ho")
}
diff --git a/kotlin-baseball/src/main/kotlin/baseball/KtInActionPart1.kt b/kotlin-baseball/src/main/kotlin/baseball/KtInActionPart1.kt
new file mode 100644
index 0000000..d6d5893
--- /dev/null
+++ b/kotlin-baseball/src/main/kotlin/baseball/KtInActionPart1.kt
@@ -0,0 +1,35 @@
+package baseball
+
+/*
+* 코틀린의 주요 특성
+* 코틀린을 도입하면 더 적은 코드로 더 편하게 프로그래머의 목표를 달성할 수 있다.
+*
+* 정적 타입 지정 언어
+* 자바랑 똑같이 타입을 컴파일 시점에 알 수 있음.
+* 이로 인해서 오는 장점이 성능, 신뢰성, 유지 보수성, 도구 지원 등이 있다고 함. 개인적으로는 컴파일 안 하는 언어는 왜 쓰는지 모르겠음 ㅋㅋ;
+*
+* 함수형 프로그래밍과 객체지향 프로그래밍
+* 어제 자면서 본 레퍼런스에서 코틀린과 스칼라가 자주 비교됨. 이유는 스칼라가 함수형 프로그래밍 언어이기 때문인 것 같은데 코틀린도 함수형 프로그래밍 언어를 좋아함.
+* 함수형 프로그래밍의 장점
+* 1. 간결함. 명령형(imperative) 코드에 비해 더 간결하며 우아함.
+* 2. 다중 스레드에도 안전함. 불변 데이터 구조를 사용하고 순수 함수를 그 데이터 구조에 적용하면 같은 데이터를 여러 스레드가 변경할 수 없음. 그래서 복잡한 동기화를 적용하지 않아도 됨. (아직 이해 x)
+* 3. 테스트하기 쉬움. 자바는 전체 환경을 구성하는 준비 코드가 필요한데 순수 함수는 그런 준비 없이 독립적으로 테스트가 가능하다고 함. 이번 스터디에서 이 부분에 대해 공부해 봐야 할 듯!!
+*
+* 코틀린의 철학
+* 실용성
+* 코틀린은 실제 문제를 해결하기 위해 만들어진 언어라고 함. 연구를 하기 위한 언어가 아니고 이미 성공적으로 검증된 해법과 기능에 의존함. 이 부분이 개인적으로 마음에 듬.
+*
+* 간결성
+* 개인적으로 자바에서 쓸모없는 코드가 몇 개 보였음. private final 같은.. 자바는 쓸모 없는 코드 때문에 코드의 양이 엄청 많아짐.
+* 이렇게 코드의 양이 많아지면 읽기가 싫어지고 유지보수하기 싫어짐. 이는 공학작문및발표 수업에서 배웠고 매우 동의하는 바임.
+* 코드가 간결할수록 내용을 파악하기 더 쉬움. 코틀린은 간결하면서도 의도를 쉽게 파악할 수 있는 구문 구조를 제공함. 이 부분도 개인적으로 마음에 듬.
+* 하지만 책을 조금 읽어봤을 때 너무 간결해 오히려 불편함.. 조금 적응하면 나아질 수 있다고 생각함.
+*
+* 안전성
+* 코틀린은 자바보다 NPE에 안전함. 보통 언어가 안전하다면 생산성이 하락하는데 코틀린에서는 ? 한 글자만 추가하면 됨. 굉장히 간결함.
+* 또, 타입 캐스팅을 할 때도 극도로 간결함. 자바의 필요 없는 구문들이 거의 제거 됨.
+*
+* */
+
+class KtInActionPart1 {
+}
\ No newline at end of file
From 2041c49c8243c7f6bd68fdeffb1196c97447a84a Mon Sep 17 00:00:00 2001
From: leesoobeen <02ggang9@gmail.com>
Date: Tue, 13 Feb 2024 15:14:19 +0900
Subject: [PATCH 2/8] =?UTF-8?q?feat:=20=EC=BD=94=ED=8B=80=EB=A6=B0=20?=
=?UTF-8?q?=EC=9D=B8=20=EC=95=A1=EC=85=98=20=ED=8C=8C=ED=8A=B8=202=20?=
=?UTF-8?q?=EC=A0=95=EB=A6=AC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.idea/gradle.xml | 4 +-
.../main/kotlin/baseball/KtInActionPart2.kt | 12 ++
.../main/kotlin/baseball/KtInActionPart3.kt | 2 +
.../test/kotlin/baseball/KtInActionPart2.kt | 164 ++++++++++++++++++
4 files changed, 181 insertions(+), 1 deletion(-)
create mode 100644 kotlin-baseball/src/main/kotlin/baseball/KtInActionPart2.kt
create mode 100644 kotlin-baseball/src/main/kotlin/baseball/KtInActionPart3.kt
create mode 100644 kotlin-baseball/src/test/kotlin/baseball/KtInActionPart2.kt
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index bd326f3..99c3817 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -3,8 +3,10 @@
+
+
-
+
diff --git a/kotlin-baseball/src/main/kotlin/baseball/KtInActionPart2.kt b/kotlin-baseball/src/main/kotlin/baseball/KtInActionPart2.kt
new file mode 100644
index 0000000..11eb7ce
--- /dev/null
+++ b/kotlin-baseball/src/main/kotlin/baseball/KtInActionPart2.kt
@@ -0,0 +1,12 @@
+package baseball
+
+/*
+*
+*
+*
+* */
+
+
+class KtInActionPart2 {
+
+}
\ No newline at end of file
diff --git a/kotlin-baseball/src/main/kotlin/baseball/KtInActionPart3.kt b/kotlin-baseball/src/main/kotlin/baseball/KtInActionPart3.kt
new file mode 100644
index 0000000..e9f5535
--- /dev/null
+++ b/kotlin-baseball/src/main/kotlin/baseball/KtInActionPart3.kt
@@ -0,0 +1,2 @@
+package baseball
+
diff --git a/kotlin-baseball/src/test/kotlin/baseball/KtInActionPart2.kt b/kotlin-baseball/src/test/kotlin/baseball/KtInActionPart2.kt
new file mode 100644
index 0000000..7f113ac
--- /dev/null
+++ b/kotlin-baseball/src/test/kotlin/baseball/KtInActionPart2.kt
@@ -0,0 +1,164 @@
+package baseball
+
+import org.junit.jupiter.api.Test
+import java.io.BufferedReader
+import java.io.StringReader
+import java.util.TreeMap
+
+class KtInActionPart2Test {
+
+ @Test
+ fun printHelloWorld() {
+ println("Hello, World")
+ }
+
+ @Test
+ fun maxTest() {
+ println(max(3, 2))
+ println(max(2,4))
+ }
+
+ /*
+ * 식이 본문인 함수의 반환 타입만 생략이 가능하다.
+ * */
+ private fun max(a: Int, b: Int): Int = if (a > b) a else b
+
+ @Test
+ fun variable() {
+ val languages = arrayListOf("Java")
+ languages.add("Kotlin")
+ println(languages)
+ }
+
+ @Test
+ fun stringTemplate() {
+ val name = "Kotlin"
+ println("Hello, $name!")
+ println("Hello, ${name}님 반가워용")
+// println("Hello, $name님 반가워용")
+ }
+
+ @Test
+ fun classTest() {
+ val person = Person("ggang9", false)
+ println(person.name)
+ println(person.isMarried)
+ println(person)
+ }
+
+ class Person (
+ val name: String,
+ val isMarried: Boolean
+ )
+
+ @Test
+ fun enumTest() {
+ println(Color2.BLUE.rgb())
+ }
+
+ enum class Color {
+ RED, ORANGE, YELLOW
+ }
+
+ enum class Color2(
+ val r: Int, val g: Int, val b: Int
+ ) {
+ RED(255, 0, 0),
+ ORANGE(0, 255, 0),
+ BLUE(0, 0, 255)
+ ;
+
+ fun rgb() = (r * 256 + g) % 256 + b
+ }
+
+ @Test
+ fun enumTest2() {
+ println(getMnemonic(Color2.BLUE))
+ }
+
+ private fun getMnemonic(color: Color2) =
+ when (color) {
+ Color2.RED -> "Richard"
+ Color2.BLUE -> "Battle"
+ Color2.ORANGE -> "Of"
+ }
+
+ @Test
+ fun testForLoop() {
+ for (i in 1..100) {
+ println(fizzBuzz(i))
+ }
+ }
+
+ private fun fizzBuzz(i: Int) = when {
+ i % 15 == 0 -> "FizzBuzz"
+ i % 3 == 0 -> "Fizz"
+ i % 5 == 0 -> "Buzz"
+ else -> "${i}"
+ }
+
+ @Test
+ fun testForLoop2() {
+ for (i in 100 downTo 1 step 2) {
+ println(fizzBuzz(i))
+ }
+ }
+
+ @Test
+ fun testMapIter() {
+ val binaryReps = TreeMap()
+ for (c in 'A'..'F') {
+ val binary = Integer.toBinaryString(c.code)
+ binaryReps[c] = binary
+ }
+
+ for ((letter, binary) in binaryReps) {
+ println("$letter = $binary")
+ }
+ }
+
+ @Test
+ fun testWhenIn() {
+ println(recognize('B'))
+ }
+
+ private 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"
+ }
+
+ @Test
+ fun readNumber() {
+ println(readNumber(BufferedReader(StringReader("not a number"))))
+ }
+
+ private fun readNumber(reader: BufferedReader) {
+ val number = try {
+ Integer.parseInt(reader.readLine())
+ } catch (e: NumberFormatException) {
+ null
+ }
+ }
+
+ @Test
+ fun testJoinToString() {
+ val list = listOf(1, 2, 3)
+ println(joinToString(list, "; ", "(", ")"))
+ }
+
+ private fun joinToString(collection: Collection,
+ separator: String,
+ prefix: String,
+ postfix: String): String {
+ val result = StringBuilder(prefix)
+ for ((index, element) in collection.withIndex()) {
+ if (index > 0) result.append(separator)
+ result.append(element)
+ }
+
+ result.append(postfix)
+ return result.toString()
+ }
+
+}
\ No newline at end of file
From bd1783e2c3ebac46da0ed8791ebe2a35c0fd800d Mon Sep 17 00:00:00 2001
From: leesoobeen <02ggang9@gmail.com>
Date: Tue, 13 Feb 2024 17:28:43 +0900
Subject: [PATCH 3/8] =?UTF-8?q?feat:=20=EC=BD=94=ED=8B=80=EB=A6=B0=20?=
=?UTF-8?q?=EC=9D=B8=20=EC=95=A1=EC=85=98=20=ED=8C=8C=ED=8A=B8=203=20?=
=?UTF-8?q?=EC=A0=95=EB=A6=AC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../src/main/kotlin/KtInActionUtil/JointKt.kt | 45 +++++++
.../test/kotlin/baseball/KtInActionPart2.kt | 19 ---
.../test/kotlin/baseball/KtInActionPart3.kt | 122 ++++++++++++++++++
3 files changed, 167 insertions(+), 19 deletions(-)
create mode 100644 kotlin-baseball/src/main/kotlin/KtInActionUtil/JointKt.kt
create mode 100644 kotlin-baseball/src/test/kotlin/baseball/KtInActionPart3.kt
diff --git a/kotlin-baseball/src/main/kotlin/KtInActionUtil/JointKt.kt b/kotlin-baseball/src/main/kotlin/KtInActionUtil/JointKt.kt
new file mode 100644
index 0000000..f507d88
--- /dev/null
+++ b/kotlin-baseball/src/main/kotlin/KtInActionUtil/JointKt.kt
@@ -0,0 +1,45 @@
+package KtInActionUtil
+
+const val UNIT_LINE_SEPARATOR = "\n"
+
+fun joinToString(collection: Collection,
+ separator: String,
+ prefix: String,
+ postfix: String): String {
+ val result = StringBuilder(prefix)
+ for ((index, element) in collection.withIndex()) {
+ if (index > 0) result.append(separator)
+ result.append(element)
+ }
+
+ result.append(postfix)
+ return result.toString()
+}
+
+fun String.lastChar(): Char = this.get(length - 1)
+
+var StringBuilder.lastChar: Char
+ get() = get(length - 1)
+ set(value: Char) {
+ this.setCharAt(length - 1, value)
+ }
+
+fun Collection.joinToString2(
+ separator: String = ", ",
+ prefix: String = "",
+ postfix: String = ""
+): String {
+ val result = StringBuilder(prefix)
+ for ((index, element) in this.withIndex()) {
+ if (index > 0) result.append(separator)
+ result.append(element)
+ }
+ result.append(postfix)
+ return result.toString()
+}
+
+fun Collection.joinToString3(
+ separator: String = ", ",
+ prefix: String = "",
+ postfix: String = ""
+) = joinToString2(separator, prefix, postfix)
\ No newline at end of file
diff --git a/kotlin-baseball/src/test/kotlin/baseball/KtInActionPart2.kt b/kotlin-baseball/src/test/kotlin/baseball/KtInActionPart2.kt
index 7f113ac..ffd1787 100644
--- a/kotlin-baseball/src/test/kotlin/baseball/KtInActionPart2.kt
+++ b/kotlin-baseball/src/test/kotlin/baseball/KtInActionPart2.kt
@@ -141,24 +141,5 @@ class KtInActionPart2Test {
}
}
- @Test
- fun testJoinToString() {
- val list = listOf(1, 2, 3)
- println(joinToString(list, "; ", "(", ")"))
- }
-
- private fun joinToString(collection: Collection,
- separator: String,
- prefix: String,
- postfix: String): String {
- val result = StringBuilder(prefix)
- for ((index, element) in collection.withIndex()) {
- if (index > 0) result.append(separator)
- result.append(element)
- }
-
- result.append(postfix)
- return result.toString()
- }
}
\ No newline at end of file
diff --git a/kotlin-baseball/src/test/kotlin/baseball/KtInActionPart3.kt b/kotlin-baseball/src/test/kotlin/baseball/KtInActionPart3.kt
new file mode 100644
index 0000000..3f12140
--- /dev/null
+++ b/kotlin-baseball/src/test/kotlin/baseball/KtInActionPart3.kt
@@ -0,0 +1,122 @@
+package baseball
+
+import KtInActionUtil.*
+import org.junit.jupiter.api.Test
+
+
+class KtInActionPart3Test {
+
+ @Test
+ fun testJoinToString() {
+ val list = listOf(1, 2, 3)
+ println(joinToString(list, "; ", "(", ")"))
+ }
+
+ @Test
+ fun testJoinToString2() {
+ val collection = listOf(1, 2, 3)
+ println(joinToString(collection, separator = " ", prefix = " ", postfix = "."))
+ }
+
+ @Test
+ fun utilPropertyTest() {
+ println(UNIT_LINE_SEPARATOR)
+ }
+
+ @Test
+ fun extensionFun1() {
+ println("Kotlin".lastChar())
+ }
+
+ @Test
+ fun extensionFun2() {
+ val list = listOf(1, 2, 3)
+ println(list.joinToString2(" "))
+ }
+
+ @Test
+ fun extensionFun3() {
+ val list = listOf("one", "two", "three", "eight")
+ println(list.joinToString3(" "))
+ }
+
+ @Test
+ fun spreadTest() {
+ val list = arrayOf("String", "Java", "Kotlin")
+ spread(list)
+ }
+
+ private fun spread(args: Array) {
+ println(listOf("args: ", *args))
+ }
+
+ @Test
+ fun mapToTest() {
+ val map = mapOf(1 to "one", 7 to "seven", 53 to "fifty-three")
+ println(map)
+ }
+
+ @Test
+ fun splitTest() {
+ println("12.345-6.A".split(".", "-"))
+ }
+
+ @Test
+ fun parseTest() {
+ val path = "/Users/yole/kotlin-book/chapter.adoc"
+ parsePath(path)
+ }
+
+ private fun parsePath(path: String) {
+ val directory = path.substringBeforeLast("/")
+ val fullName = path.substringAfterLast("/")
+ val fileName = fullName.substringBefore(".")
+ val extension = path.substringAfterLast(".")
+ println("Dir: $directory, name: $fileName, ext: $extension")
+ }
+
+ @Test
+ fun StringTest() {
+ println("""
+ | //
+ | //
+ | /\
+ """.trimIndent())
+ }
+
+ class User(
+ val id: Int,
+ val name: String,
+ val address: String
+ )
+
+ private fun saveUser(user: User) {
+ fun validate(user: User,
+ value: String,
+ fieldName: String) {
+ if (value.isEmpty()) {
+ throw IllegalArgumentException("Can't save User ${user.id}: empty $fieldName")
+ }
+ }
+
+ validate(user, user.name, "Name")
+ validate(user, user.address, "Address")
+ }
+
+ /*
+ * Issue Entity 클래스에 몰빵 vs 디렉토리 나눠서 확장 함수로 관리? -> (p.138 list 3.14) 자바는 어쩔 수 없이 클래스 안에 몰빵해야 하는데 코틀린은 확장 함수 때문에 분리해서 관리할 수 있음.
+ * Issue Builder vs 생성자 -> 커맨드 + P + p.108
+ * */
+
+ private fun saveUser2(user: User) {
+ fun validate(value: String, fieldName: String) {
+ if (value.isEmpty()) {
+ throw IllegalArgumentException("Can't save User ${user.id}: empty $fieldName")
+ }
+ }
+
+ validate(user.name, "Name")
+ validate(user.address, "Address")
+ }
+
+}
From 43ba7408671d168e9f7f78243f53bd7abca30f70 Mon Sep 17 00:00:00 2001
From: leesoobeen <02ggang9@gmail.com>
Date: Tue, 13 Feb 2024 21:05:25 +0900
Subject: [PATCH 4/8] =?UTF-8?q?chore:=20=ED=8C=8C=EC=9D=BC=20=EB=94=94?=
=?UTF-8?q?=EB=A0=89=ED=86=A0=EB=A6=AC=20=EB=B3=80=EA=B2=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../{baseball => KtInActionUtil}/KtInActionPart1.kt | 2 +-
.../src/main/kotlin/baseball/KtInActionPart2.kt | 12 ------------
.../src/main/kotlin/baseball/KtInActionPart3.kt | 2 --
.../KtInActionPart2.kt | 2 +-
.../KtInActionPart3.kt | 2 +-
5 files changed, 3 insertions(+), 17 deletions(-)
rename kotlin-baseball/src/main/kotlin/{baseball => KtInActionUtil}/KtInActionPart1.kt (99%)
delete mode 100644 kotlin-baseball/src/main/kotlin/baseball/KtInActionPart2.kt
delete mode 100644 kotlin-baseball/src/main/kotlin/baseball/KtInActionPart3.kt
rename kotlin-baseball/src/test/kotlin/{baseball => KtInActionPractice}/KtInActionPart2.kt (99%)
rename kotlin-baseball/src/test/kotlin/{baseball => KtInActionPractice}/KtInActionPart3.kt (99%)
diff --git a/kotlin-baseball/src/main/kotlin/baseball/KtInActionPart1.kt b/kotlin-baseball/src/main/kotlin/KtInActionUtil/KtInActionPart1.kt
similarity index 99%
rename from kotlin-baseball/src/main/kotlin/baseball/KtInActionPart1.kt
rename to kotlin-baseball/src/main/kotlin/KtInActionUtil/KtInActionPart1.kt
index d6d5893..840a405 100644
--- a/kotlin-baseball/src/main/kotlin/baseball/KtInActionPart1.kt
+++ b/kotlin-baseball/src/main/kotlin/KtInActionUtil/KtInActionPart1.kt
@@ -1,4 +1,4 @@
-package baseball
+package KtInActionUtil
/*
* 코틀린의 주요 특성
diff --git a/kotlin-baseball/src/main/kotlin/baseball/KtInActionPart2.kt b/kotlin-baseball/src/main/kotlin/baseball/KtInActionPart2.kt
deleted file mode 100644
index 11eb7ce..0000000
--- a/kotlin-baseball/src/main/kotlin/baseball/KtInActionPart2.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-package baseball
-
-/*
-*
-*
-*
-* */
-
-
-class KtInActionPart2 {
-
-}
\ No newline at end of file
diff --git a/kotlin-baseball/src/main/kotlin/baseball/KtInActionPart3.kt b/kotlin-baseball/src/main/kotlin/baseball/KtInActionPart3.kt
deleted file mode 100644
index e9f5535..0000000
--- a/kotlin-baseball/src/main/kotlin/baseball/KtInActionPart3.kt
+++ /dev/null
@@ -1,2 +0,0 @@
-package baseball
-
diff --git a/kotlin-baseball/src/test/kotlin/baseball/KtInActionPart2.kt b/kotlin-baseball/src/test/kotlin/KtInActionPractice/KtInActionPart2.kt
similarity index 99%
rename from kotlin-baseball/src/test/kotlin/baseball/KtInActionPart2.kt
rename to kotlin-baseball/src/test/kotlin/KtInActionPractice/KtInActionPart2.kt
index ffd1787..70b533b 100644
--- a/kotlin-baseball/src/test/kotlin/baseball/KtInActionPart2.kt
+++ b/kotlin-baseball/src/test/kotlin/KtInActionPractice/KtInActionPart2.kt
@@ -1,4 +1,4 @@
-package baseball
+package KtInActionPractice
import org.junit.jupiter.api.Test
import java.io.BufferedReader
diff --git a/kotlin-baseball/src/test/kotlin/baseball/KtInActionPart3.kt b/kotlin-baseball/src/test/kotlin/KtInActionPractice/KtInActionPart3.kt
similarity index 99%
rename from kotlin-baseball/src/test/kotlin/baseball/KtInActionPart3.kt
rename to kotlin-baseball/src/test/kotlin/KtInActionPractice/KtInActionPart3.kt
index 3f12140..fa3a251 100644
--- a/kotlin-baseball/src/test/kotlin/baseball/KtInActionPart3.kt
+++ b/kotlin-baseball/src/test/kotlin/KtInActionPractice/KtInActionPart3.kt
@@ -1,4 +1,4 @@
-package baseball
+package KtInActionPractice
import KtInActionUtil.*
import org.junit.jupiter.api.Test
From 780083007835af1d2a11481879f3249d0c237588 Mon Sep 17 00:00:00 2001
From: leesoobeen <02ggang9@gmail.com>
Date: Tue, 13 Feb 2024 22:56:05 +0900
Subject: [PATCH 5/8] =?UTF-8?q?feat:=20=EC=88=AB=EC=9E=90=20=EC=95=BC?=
=?UTF-8?q?=EA=B5=AC=201=EC=B0=A8=20=EA=B5=AC=ED=98=84?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../JointKt.kt | 2 +-
.../KtInActionPart1.kt | 2 +-
.../src/main/kotlin/baseball/Application.kt | 26 +++++++++-
.../src/main/kotlin/step1/BaseBallGame.kt | 52 +++++++++++++++++++
.../KtInActionPractice/KtInActionPart3.kt | 1 -
5 files changed, 79 insertions(+), 4 deletions(-)
rename kotlin-baseball/src/main/kotlin/{KtInActionUtil => KtInActionPractice}/JointKt.kt (97%)
rename kotlin-baseball/src/main/kotlin/{KtInActionUtil => KtInActionPractice}/KtInActionPart1.kt (99%)
create mode 100644 kotlin-baseball/src/main/kotlin/step1/BaseBallGame.kt
diff --git a/kotlin-baseball/src/main/kotlin/KtInActionUtil/JointKt.kt b/kotlin-baseball/src/main/kotlin/KtInActionPractice/JointKt.kt
similarity index 97%
rename from kotlin-baseball/src/main/kotlin/KtInActionUtil/JointKt.kt
rename to kotlin-baseball/src/main/kotlin/KtInActionPractice/JointKt.kt
index f507d88..0cff2c0 100644
--- a/kotlin-baseball/src/main/kotlin/KtInActionUtil/JointKt.kt
+++ b/kotlin-baseball/src/main/kotlin/KtInActionPractice/JointKt.kt
@@ -1,4 +1,4 @@
-package KtInActionUtil
+package KtInActionPractice
const val UNIT_LINE_SEPARATOR = "\n"
diff --git a/kotlin-baseball/src/main/kotlin/KtInActionUtil/KtInActionPart1.kt b/kotlin-baseball/src/main/kotlin/KtInActionPractice/KtInActionPart1.kt
similarity index 99%
rename from kotlin-baseball/src/main/kotlin/KtInActionUtil/KtInActionPart1.kt
rename to kotlin-baseball/src/main/kotlin/KtInActionPractice/KtInActionPart1.kt
index 840a405..2584196 100644
--- a/kotlin-baseball/src/main/kotlin/KtInActionUtil/KtInActionPart1.kt
+++ b/kotlin-baseball/src/main/kotlin/KtInActionPractice/KtInActionPart1.kt
@@ -1,4 +1,4 @@
-package KtInActionUtil
+package KtInActionPractice
/*
* 코틀린의 주요 특성
diff --git a/kotlin-baseball/src/main/kotlin/baseball/Application.kt b/kotlin-baseball/src/main/kotlin/baseball/Application.kt
index 603d348..5b4a238 100644
--- a/kotlin-baseball/src/main/kotlin/baseball/Application.kt
+++ b/kotlin-baseball/src/main/kotlin/baseball/Application.kt
@@ -1,5 +1,29 @@
package baseball
+import camp.nextstep.edu.missionutils.Console
+import camp.nextstep.edu.missionutils.Randoms
+import step1.*
+
fun main() {
- print("ho")
+ announceBaseballGameStartMessage()
+ var randomNumbers = pickRandomNumbers()
+
+ while (true) {
+ announceEnterNumbersMessage()
+ val readLine = Console.readLine()
+ if (!isUserInputValid(readLine)) {
+ throw IllegalArgumentException()
+ }
+
+ announceBaseballResult(readLine, randomNumbers)
+ if (readLine.isThreeStrike(readLine, randomNumbers)) {
+ announceThreeStrike()
+ announceBaseballRestartMessage()
+ if (Console.readLine() == "2") break
+ randomNumbers = pickRandomNumbers()
+ }
+ }
}
+
+fun String.isThreeStrike(numbers: String, randomNumbers: String): Boolean =
+ numbers[0] == randomNumbers[0] && numbers[1] == randomNumbers[1] && numbers[2] == randomNumbers[2]
diff --git a/kotlin-baseball/src/main/kotlin/step1/BaseBallGame.kt b/kotlin-baseball/src/main/kotlin/step1/BaseBallGame.kt
new file mode 100644
index 0000000..aa8845d
--- /dev/null
+++ b/kotlin-baseball/src/main/kotlin/step1/BaseBallGame.kt
@@ -0,0 +1,52 @@
+package step1
+
+import camp.nextstep.edu.missionutils.Randoms
+
+fun announceBaseballGameStartMessage() = println("숫자 야구 게임을 시작합니다.")
+
+fun announceEnterNumbersMessage() = print("숫자를 입력해주세요 : ")
+
+fun announceThreeStrike() = println("3개의 숫자를 모두 맞히셨습니다! 게임 종료")
+
+fun announceBaseballRestartMessage() = println("게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요.")
+
+fun announceBaseballResult(userInputNumbers: String, randomNumbers: String) = println(calculateBaseballGameResult(userInputNumbers, randomNumbers))
+
+fun pickRandomNumbers(): String {
+ val randomNumbers = mutableListOf()
+ while (randomNumbers.size < 3) {
+ val randomNumber = Randoms.pickNumberInRange(1, 9)
+ if (!randomNumbers.contains(randomNumber)) {
+ randomNumbers.add(randomNumber)
+ }
+ }
+ return randomNumbers.joinToString(separator = "")
+}
+
+fun isUserInputValid(userInputNumbers: String): Boolean = userInputNumbers.length == 3 && userInputNumbers.toIntOrNull() != null
+
+
+private fun calculateBaseballGameResult(userInputNumbers: String, randomNumbers: String): String {
+ val result = StringBuilder()
+ var strikeCount = 0
+ var ballCount = 0
+
+ for (i in randomNumbers.indices) {
+ if (userInputNumbers[i] == randomNumbers[i]) {
+ strikeCount++
+ } else if (userInputNumbers[i] in randomNumbers) {
+ ballCount++
+ }
+ }
+
+ if (ballCount > 0) {
+ result.append("${ballCount}볼 ")
+ }
+
+ if (strikeCount > 0) {
+ result.append("${strikeCount}스트라이크")
+ }
+
+ return if (ballCount == 0 && strikeCount == 0) "낫싱" else result.toString()
+
+}
\ No newline at end of file
diff --git a/kotlin-baseball/src/test/kotlin/KtInActionPractice/KtInActionPart3.kt b/kotlin-baseball/src/test/kotlin/KtInActionPractice/KtInActionPart3.kt
index fa3a251..9502b15 100644
--- a/kotlin-baseball/src/test/kotlin/KtInActionPractice/KtInActionPart3.kt
+++ b/kotlin-baseball/src/test/kotlin/KtInActionPractice/KtInActionPart3.kt
@@ -1,6 +1,5 @@
package KtInActionPractice
-import KtInActionUtil.*
import org.junit.jupiter.api.Test
From 255fefcdc57783b840488a7b55084fbfbbd1be41 Mon Sep 17 00:00:00 2001
From: leesoobeen <02ggang9@gmail.com>
Date: Tue, 13 Feb 2024 22:59:50 +0900
Subject: [PATCH 6/8] =?UTF-8?q?fix:=201=EC=B0=A8=20=EA=B5=AC=ED=98=84=20?=
=?UTF-8?q?=EB=B6=84=EB=A6=AC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../src/main/kotlin/baseball/Application.kt | 22 +--------------
.../kotlin/step1/StepOneBaseballGameMain.kt | 28 +++++++++++++++++++
2 files changed, 29 insertions(+), 21 deletions(-)
create mode 100644 kotlin-baseball/src/main/kotlin/step1/StepOneBaseballGameMain.kt
diff --git a/kotlin-baseball/src/main/kotlin/baseball/Application.kt b/kotlin-baseball/src/main/kotlin/baseball/Application.kt
index 5b4a238..c3e0576 100644
--- a/kotlin-baseball/src/main/kotlin/baseball/Application.kt
+++ b/kotlin-baseball/src/main/kotlin/baseball/Application.kt
@@ -1,29 +1,9 @@
package baseball
import camp.nextstep.edu.missionutils.Console
-import camp.nextstep.edu.missionutils.Randoms
import step1.*
fun main() {
- announceBaseballGameStartMessage()
- var randomNumbers = pickRandomNumbers()
-
- while (true) {
- announceEnterNumbersMessage()
- val readLine = Console.readLine()
- if (!isUserInputValid(readLine)) {
- throw IllegalArgumentException()
- }
-
- announceBaseballResult(readLine, randomNumbers)
- if (readLine.isThreeStrike(readLine, randomNumbers)) {
- announceThreeStrike()
- announceBaseballRestartMessage()
- if (Console.readLine() == "2") break
- randomNumbers = pickRandomNumbers()
- }
- }
+ stepOneRunner()
}
-fun String.isThreeStrike(numbers: String, randomNumbers: String): Boolean =
- numbers[0] == randomNumbers[0] && numbers[1] == randomNumbers[1] && numbers[2] == randomNumbers[2]
diff --git a/kotlin-baseball/src/main/kotlin/step1/StepOneBaseballGameMain.kt b/kotlin-baseball/src/main/kotlin/step1/StepOneBaseballGameMain.kt
new file mode 100644
index 0000000..02d5283
--- /dev/null
+++ b/kotlin-baseball/src/main/kotlin/step1/StepOneBaseballGameMain.kt
@@ -0,0 +1,28 @@
+package step1
+
+import camp.nextstep.edu.missionutils.Console
+
+fun stepOneRunner() {
+ announceBaseballGameStartMessage()
+ var randomNumbers = pickRandomNumbers()
+
+ while (true) {
+ announceEnterNumbersMessage()
+ val readLine = Console.readLine()
+ if (!isUserInputValid(readLine)) {
+ throw IllegalArgumentException()
+ }
+
+ announceBaseballResult(readLine, randomNumbers)
+ if (readLine.isThreeStrike(readLine, randomNumbers)) {
+ announceThreeStrike()
+ announceBaseballRestartMessage()
+ if (Console.readLine() == "2") break
+ randomNumbers = pickRandomNumbers()
+ }
+ }
+}
+
+
+fun String.isThreeStrike(numbers: String, randomNumbers: String): Boolean =
+ numbers[0] == randomNumbers[0] && numbers[1] == randomNumbers[1] && numbers[2] == randomNumbers[2]
\ No newline at end of file
From 0782aa89101fe63202997ec969d26fac433339dc Mon Sep 17 00:00:00 2001
From: leesoobeen <02ggang9@gmail.com>
Date: Thu, 15 Feb 2024 20:26:39 +0900
Subject: [PATCH 7/8] =?UTF-8?q?feat:=202=EC=B0=A8=20=EA=B5=AC=ED=98=84=20?=
=?UTF-8?q?=EC=99=84=EB=A3=8C?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../src/main/kotlin/baseball/Application.kt | 7 +-
.../kotlin/step2/api/BaseballController.kt | 26 ++++
.../step2/application/BaseballService.kt | 17 +++
.../kotlin/step2/dto/BaseballResultDto.kt | 6 +
.../main/kotlin/step2/entity/RandomNumbers.kt | 14 ++
.../kotlin/step2/global/ExtensionUtils.kt | 12 ++
.../kotlin/step2/global/RunApplication.kt | 48 +++++++
.../main/kotlin/step2/view/BaseballView.kt | 20 +++
.../{ => chapter2}/KtInActionPart2.kt | 2 +-
.../{ => chapter3}/KtInActionPart3.kt | 3 +-
.../KtInActionPractice/chapter4/Clickable.kt | 10 ++
.../KtInActionPractice/chapter4/Focusable.kt | 8 ++
.../chapter4/KtInActionPart4.kt | 133 ++++++++++++++++++
13 files changed, 302 insertions(+), 4 deletions(-)
create mode 100644 kotlin-baseball/src/main/kotlin/step2/api/BaseballController.kt
create mode 100644 kotlin-baseball/src/main/kotlin/step2/application/BaseballService.kt
create mode 100644 kotlin-baseball/src/main/kotlin/step2/dto/BaseballResultDto.kt
create mode 100644 kotlin-baseball/src/main/kotlin/step2/entity/RandomNumbers.kt
create mode 100644 kotlin-baseball/src/main/kotlin/step2/global/ExtensionUtils.kt
create mode 100644 kotlin-baseball/src/main/kotlin/step2/global/RunApplication.kt
create mode 100644 kotlin-baseball/src/main/kotlin/step2/view/BaseballView.kt
rename kotlin-baseball/src/test/kotlin/KtInActionPractice/{ => chapter2}/KtInActionPart2.kt (98%)
rename kotlin-baseball/src/test/kotlin/KtInActionPractice/{ => chapter3}/KtInActionPart3.kt (97%)
create mode 100644 kotlin-baseball/src/test/kotlin/KtInActionPractice/chapter4/Clickable.kt
create mode 100644 kotlin-baseball/src/test/kotlin/KtInActionPractice/chapter4/Focusable.kt
create mode 100644 kotlin-baseball/src/test/kotlin/KtInActionPractice/chapter4/KtInActionPart4.kt
diff --git a/kotlin-baseball/src/main/kotlin/baseball/Application.kt b/kotlin-baseball/src/main/kotlin/baseball/Application.kt
index c3e0576..2aef0d7 100644
--- a/kotlin-baseball/src/main/kotlin/baseball/Application.kt
+++ b/kotlin-baseball/src/main/kotlin/baseball/Application.kt
@@ -1,9 +1,12 @@
package baseball
-import camp.nextstep.edu.missionutils.Console
import step1.*
+import step2.api.BaseballController
+import step2.application.BaseballService
+import step2.global.BaseballApplication
+import step2.view.BaseballView
fun main() {
- stepOneRunner()
+ BaseballApplication(BaseballView(), BaseballController(BaseballService())).run()
}
diff --git a/kotlin-baseball/src/main/kotlin/step2/api/BaseballController.kt b/kotlin-baseball/src/main/kotlin/step2/api/BaseballController.kt
new file mode 100644
index 0000000..0bebec4
--- /dev/null
+++ b/kotlin-baseball/src/main/kotlin/step2/api/BaseballController.kt
@@ -0,0 +1,26 @@
+package step2.api
+
+import step2.application.BaseballService
+import step2.dto.BaseballResultDto
+import step2.view.BaseballView
+
+class BaseballController(
+ val baseballService: BaseballService
+) {
+
+ fun saveRandomNumbers() {
+ baseballService.createBaseball()
+ }
+
+ fun getBaseballGameResult(userInputNumbers: String): BaseballResultDto {
+
+ // 어노테이션으로 만들어보면 어떨까용?
+ if (!(userInputNumbers.length == 3 && userInputNumbers.toIntOrNull() != null)) {
+ throw IllegalArgumentException()
+ }
+
+ return baseballService.compareRandomNumbers(userInputNumbers)
+
+ }
+
+}
\ No newline at end of file
diff --git a/kotlin-baseball/src/main/kotlin/step2/application/BaseballService.kt b/kotlin-baseball/src/main/kotlin/step2/application/BaseballService.kt
new file mode 100644
index 0000000..cd703a0
--- /dev/null
+++ b/kotlin-baseball/src/main/kotlin/step2/application/BaseballService.kt
@@ -0,0 +1,17 @@
+package step2.application
+
+import step2.dto.BaseballResultDto
+import step2.entity.RandomNumbers
+import step2.global.createUniqueRandomNumbers
+
+class BaseballService {
+
+ fun createBaseball() {
+ val createUniqueRandomNumbers = createUniqueRandomNumbers(3)
+ RandomNumbers.changeRandomNumbers(createUniqueRandomNumbers)
+ }
+
+ fun compareRandomNumbers(userInputNumbers: String): BaseballResultDto =
+ BaseballResultDto(RandomNumbers.countStrike(userInputNumbers), RandomNumbers.countBall(userInputNumbers))
+
+}
\ No newline at end of file
diff --git a/kotlin-baseball/src/main/kotlin/step2/dto/BaseballResultDto.kt b/kotlin-baseball/src/main/kotlin/step2/dto/BaseballResultDto.kt
new file mode 100644
index 0000000..d0f7459
--- /dev/null
+++ b/kotlin-baseball/src/main/kotlin/step2/dto/BaseballResultDto.kt
@@ -0,0 +1,6 @@
+package step2.dto
+
+data class BaseballResultDto(
+ val strikeCount: Int,
+ val ballCount: Int,
+)
diff --git a/kotlin-baseball/src/main/kotlin/step2/entity/RandomNumbers.kt b/kotlin-baseball/src/main/kotlin/step2/entity/RandomNumbers.kt
new file mode 100644
index 0000000..4b88001
--- /dev/null
+++ b/kotlin-baseball/src/main/kotlin/step2/entity/RandomNumbers.kt
@@ -0,0 +1,14 @@
+package step2.entity
+
+object RandomNumbers {
+ private var randomNumber: String? = null
+
+ fun changeRandomNumbers(number: String): String {
+ this.randomNumber = number
+ return this.randomNumber!!
+ }
+
+ fun countStrike(number: String): Int = number.indices.count { i -> number[i] == randomNumber!![i] }
+
+ fun countBall(number: String): Int = number.indices.count { i -> number[i] != randomNumber!![i] && number[i] in randomNumber!! }
+}
diff --git a/kotlin-baseball/src/main/kotlin/step2/global/ExtensionUtils.kt b/kotlin-baseball/src/main/kotlin/step2/global/ExtensionUtils.kt
new file mode 100644
index 0000000..7a530b1
--- /dev/null
+++ b/kotlin-baseball/src/main/kotlin/step2/global/ExtensionUtils.kt
@@ -0,0 +1,12 @@
+package step2.global
+
+import camp.nextstep.edu.missionutils.Console
+import camp.nextstep.edu.missionutils.Randoms
+
+fun createUniqueRandomNumbers(count: Int): String =
+ generateSequence { Randoms.pickNumberInRange(1, 9) }
+ .distinct()
+ .take(count)
+ .joinToString("")
+
+fun getThreeUniqueNumbers(): String = Console.readLine() ?: throw IllegalArgumentException()
diff --git a/kotlin-baseball/src/main/kotlin/step2/global/RunApplication.kt b/kotlin-baseball/src/main/kotlin/step2/global/RunApplication.kt
new file mode 100644
index 0000000..90ef39d
--- /dev/null
+++ b/kotlin-baseball/src/main/kotlin/step2/global/RunApplication.kt
@@ -0,0 +1,48 @@
+package step2.global
+
+import camp.nextstep.edu.missionutils.Console
+import camp.nextstep.edu.missionutils.Randoms
+import step2.api.BaseballController
+import step2.entity.RandomNumbers
+import step2.view.BaseballView
+import kotlin.system.exitProcess
+
+class BaseballApplication(
+ val baseballView: BaseballView,
+ val baseballController: BaseballController
+) {
+
+ fun run() {
+ // STEP1 > 게임 시작 문구 출력
+ baseballView.announceBaseballGameStart()
+
+ while (true) {
+ // STEP2 > 랜덤한 숫자 저장
+ baseballController.saveRandomNumbers()
+
+ // STEP3 > 숫자 입력 메시지 출력
+ baseballView.printReceiveNumberMessage()
+
+ // STEP4 > 숫자 입력
+ val userInputNumbers = getThreeUniqueNumbers()
+
+ // STEP5 > 결과 출력
+ val baseballGameResult = baseballController.getBaseballGameResult(userInputNumbers)
+
+ // STEP6 > 게임 종료 문구 출력
+ baseballView.announceGameResult(baseballGameResult)
+
+ // STEP7 > 새로 시작 or 종료
+ baseballGameResult.strikeCount.takeIf { it == 3 }
+ ?.apply { println("""
+ 3개의 숫자를 모두 맞히셨습니다! 게임 종료
+ 게임을 새로 시작하려면 1, 종료하려면 2를 입력하세요.
+ """.trimIndent()) }
+ ?.apply { Console.readLine()
+ .takeIf { it == "2" }
+ ?.apply { exitProcess(0) } }
+
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/kotlin-baseball/src/main/kotlin/step2/view/BaseballView.kt b/kotlin-baseball/src/main/kotlin/step2/view/BaseballView.kt
new file mode 100644
index 0000000..1e5e68e
--- /dev/null
+++ b/kotlin-baseball/src/main/kotlin/step2/view/BaseballView.kt
@@ -0,0 +1,20 @@
+package step2.view
+
+import step2.dto.BaseballResultDto
+
+class BaseballView {
+
+ fun announceBaseballGameStart() = println("숫자 야구 게임을 시작합니다.")
+
+ fun printReceiveNumberMessage() = print("숫자를 입력해주세요 : ")
+ fun announceGameResult(baseballGameResult: BaseballResultDto) =
+ println(
+ with(baseballGameResult) {
+ listOfNotNull(
+ ballCount.takeIf { it > 0 }?.let { "${it}볼" },
+ strikeCount.takeIf { it > 0 }?.let { "${it}스트라이크" }
+ ).takeIf { it.isNotEmpty() }?.joinToString(" ") ?: "낫싱"
+ }
+ )
+
+}
\ No newline at end of file
diff --git a/kotlin-baseball/src/test/kotlin/KtInActionPractice/KtInActionPart2.kt b/kotlin-baseball/src/test/kotlin/KtInActionPractice/chapter2/KtInActionPart2.kt
similarity index 98%
rename from kotlin-baseball/src/test/kotlin/KtInActionPractice/KtInActionPart2.kt
rename to kotlin-baseball/src/test/kotlin/KtInActionPractice/chapter2/KtInActionPart2.kt
index 70b533b..9e85ddb 100644
--- a/kotlin-baseball/src/test/kotlin/KtInActionPractice/KtInActionPart2.kt
+++ b/kotlin-baseball/src/test/kotlin/KtInActionPractice/chapter2/KtInActionPart2.kt
@@ -1,4 +1,4 @@
-package KtInActionPractice
+package KtInActionPractice.chapter2
import org.junit.jupiter.api.Test
import java.io.BufferedReader
diff --git a/kotlin-baseball/src/test/kotlin/KtInActionPractice/KtInActionPart3.kt b/kotlin-baseball/src/test/kotlin/KtInActionPractice/chapter3/KtInActionPart3.kt
similarity index 97%
rename from kotlin-baseball/src/test/kotlin/KtInActionPractice/KtInActionPart3.kt
rename to kotlin-baseball/src/test/kotlin/KtInActionPractice/chapter3/KtInActionPart3.kt
index 9502b15..7e28dc9 100644
--- a/kotlin-baseball/src/test/kotlin/KtInActionPractice/KtInActionPart3.kt
+++ b/kotlin-baseball/src/test/kotlin/KtInActionPractice/chapter3/KtInActionPart3.kt
@@ -1,5 +1,6 @@
-package KtInActionPractice
+package KtInActionPractice.chapter3
+import KtInActionPractice.*
import org.junit.jupiter.api.Test
diff --git a/kotlin-baseball/src/test/kotlin/KtInActionPractice/chapter4/Clickable.kt b/kotlin-baseball/src/test/kotlin/KtInActionPractice/chapter4/Clickable.kt
new file mode 100644
index 0000000..5adf286
--- /dev/null
+++ b/kotlin-baseball/src/test/kotlin/KtInActionPractice/chapter4/Clickable.kt
@@ -0,0 +1,10 @@
+package KtInActionPractice.chapter4
+
+
+interface Clickable {
+
+ fun click()
+
+ fun showOff() = println("I'm clickable!")
+
+}
\ No newline at end of file
diff --git a/kotlin-baseball/src/test/kotlin/KtInActionPractice/chapter4/Focusable.kt b/kotlin-baseball/src/test/kotlin/KtInActionPractice/chapter4/Focusable.kt
new file mode 100644
index 0000000..dcf52e8
--- /dev/null
+++ b/kotlin-baseball/src/test/kotlin/KtInActionPractice/chapter4/Focusable.kt
@@ -0,0 +1,8 @@
+package KtInActionPractice.chapter4
+
+interface Focusable {
+
+ fun setFocus(b: Boolean) = println("I ${if (b) "got" else "lost"} focus.")
+
+ fun showOff() = println("I'm focusable!")
+}
\ No newline at end of file
diff --git a/kotlin-baseball/src/test/kotlin/KtInActionPractice/chapter4/KtInActionPart4.kt b/kotlin-baseball/src/test/kotlin/KtInActionPractice/chapter4/KtInActionPart4.kt
new file mode 100644
index 0000000..ef56ae0
--- /dev/null
+++ b/kotlin-baseball/src/test/kotlin/KtInActionPractice/chapter4/KtInActionPart4.kt
@@ -0,0 +1,133 @@
+package KtInActionPractice.chapter4
+
+import org.junit.jupiter.api.Test
+import java.io.Serializable
+
+
+/*
+* --------------------------------
+* 추상 메서드와 디폴트 메서드를 구현할 수 있음. 다만, 아무런 상태(필드)도 들어갈 수 없음.
+* override 변경자를 꼭 붙여야 함. 어노테이션으로 하면 안됨.
+*
+* 똑같은 메서드 이름을 가진 디폴트 메서드가 있다면 둘 다 선택 x
+* 따라서 오버라이드를 통해서 명시적으로 작성을 해 줘야 함.
+*
+* 기본적으로 final 과거 스택 오버플로 조사에서는 50 : 50 으로 나눠졌다고 하는데 최종적으로 final 이 채택되었음.
+* 하위 클래스가 기반 클래스에 대해 가졌던 가정이 기반 클래스를 변경함으로써 깨져버린 경우를 대비해서 final 로 채택함 + 성능적인 문제도 있었던 걸로 기억함.
+* 따라서 상속을 허용하려면 open 변경자를 붙여야 함.
+*
+*
+*
+* */
+
+class Button: Clickable, Focusable {
+
+ override fun click() = println("I was clicked!")
+
+ override fun showOff() {
+ super.showOff()
+ super.showOff()
+ }
+
+}
+
+open class RichButton: Clickable {
+ fun disable() {}
+ open fun animate() {}
+ final override fun click() {
+
+ }
+}
+
+abstract class Animated {
+ abstract fun animate()
+
+ open fun stopAnimating() {
+
+ }
+
+ fun animateTwice() {
+
+ }
+}
+
+/*
+* 내부 클래스와 중첩된 클래스: 기본적으로 중첩 클래스
+* 클래스 안에 다른 클래스를 선언하면 도우미 클래스를 캡슐화하거나 코드 정의를 그 코드를 사용하는 곳 가까이에 두고 싶을 때 유용하다 -> 이해 잘 못 함;
+* 도우미 클래스?
+* 중첩 클래스는 명시적으로 요청하지 않는 한 바깥쪽 클래스 인스턴스에 대한 접근 권한이 없음 -> 이해 잘 못 함;
+*
+* */
+
+interface State: Serializable
+
+interface View {
+ fun getCurrentState(): State
+ fun restoreState(state: State)
+}
+
+class OtherButton: View {
+ override fun getCurrentState(): State = ButtonState()
+
+ override fun restoreState(state: State) {
+ TODO("Not yet implemented")
+ }
+
+ class ButtonState: State {
+
+ }
+
+}
+
+//interface User {
+// val nickName: String
+//}
+//
+//class PrivateUser(override val nickName: String): User
+//
+//class SubscribingUser(val email: String): User {
+// override val nickName: String
+// get() = email.substringBefore("@")
+//}
+//
+//class FacebookUser(val accountId: Int) : User {
+// override val nickName: String
+// get() = getFacebookName(accountId)
+//}
+
+class User(val name: String) {
+ var address: String = "unspecified"
+ set(value: String) {
+ println("""Address was changed for ${name}: "${field}" -> "${value}".""".trimIndent())
+ field = value
+ }
+}
+
+
+class KtInActionPart4Test {
+
+ @Test
+ fun simpleInterfaceTest() {
+ Button().click()
+ }
+
+ @Test
+ fun defaultMethodTest() {
+ Button().showOff()
+ }
+
+ @Test
+ fun showOffTest() {
+ val button = Button()
+ button.showOff()
+ button.setFocus(true)
+ button.click()
+ }
+
+ @Test
+ fun changeTest() {
+ val user = User("Alice")
+ user.address = "부산대학로 원룸"
+ }
+
+}
From 58435c46b4a18a234ca77157347b8aa1b2174d23 Mon Sep 17 00:00:00 2001
From: leesoobeen <02ggang9@gmail.com>
Date: Thu, 15 Feb 2024 23:41:57 +0900
Subject: [PATCH 8/8] =?UTF-8?q?refactor:=20=EC=BD=94=ED=8B=80=EB=A6=B0?=
=?UTF-8?q?=EC=9D=B4=20=EC=A0=9C=EA=B3=B5=ED=95=98=EB=8A=94=20=EA=B8=B0?=
=?UTF-8?q?=EB=8A=A5=EC=9D=84=20=EC=82=AC=EC=9A=A9=ED=95=B4=20=EC=98=88?=
=?UTF-8?q?=EC=99=B8=EC=B2=98=EB=A6=AC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../main/kotlin/step2/api/BaseballController.kt | 14 ++++----------
1 file changed, 4 insertions(+), 10 deletions(-)
diff --git a/kotlin-baseball/src/main/kotlin/step2/api/BaseballController.kt b/kotlin-baseball/src/main/kotlin/step2/api/BaseballController.kt
index 0bebec4..66d79a5 100644
--- a/kotlin-baseball/src/main/kotlin/step2/api/BaseballController.kt
+++ b/kotlin-baseball/src/main/kotlin/step2/api/BaseballController.kt
@@ -12,15 +12,9 @@ class BaseballController(
baseballService.createBaseball()
}
- fun getBaseballGameResult(userInputNumbers: String): BaseballResultDto {
-
- // 어노테이션으로 만들어보면 어떨까용?
- if (!(userInputNumbers.length == 3 && userInputNumbers.toIntOrNull() != null)) {
- throw IllegalArgumentException()
- }
-
- return baseballService.compareRandomNumbers(userInputNumbers)
-
- }
+ fun getBaseballGameResult(userInputNumbers: String): BaseballResultDto =
+ requireNotNull(userInputNumbers.takeIf { it.length == 3 && it.toIntOrNull() != null }) {
+ "유효하지 않은 숫자 또는 문자입니다."
+ }.let { baseballService.compareRandomNumbers(it) }
}
\ No newline at end of file