제네릭은 클래스와 같은 데이터 유형이 속성 및 메서드와 함께 사용할 수 있는 알 수 없는 자리표시자 데이터 유형을 지정하도록 허용합니다.
제네릭 적용 X)
class FillInTheBlankQuestion(
val questionText: String,
val answer: String,
val difficulty: String
)
class TrueOrFalseQuestion(
val questionText: String,
val answer: Boolean,
val difficulty: String
)
class NumericQuestion(
val questionText: String,
val answer: Int,
val difficulty: String
)
제네릭 적용 O)
class Question<T>(
val questionText: String,
val answer: T,
val difficulty: String
)
✏️ 제네릭 적용 전에 매개변수 하나의 자료형이 달라 3개의 클래스를 만들어야했지만 제네릭을 사용해 해결한 것을 확인할 수 있다.
enum이 필요한 경우
ex)
enum class Difficulty {
EASY, MEDIUM, HARD
}
클래스들은 대게 데이터와 메소드를 저장하는 형태로 이루어져 있습니다. 하지만 위에 보았던 Question 클래스처럼 메소드 없이 데이터로만 이루어진 클래스들도 존재합니다. 즉 작업을 실행하는 메소드가 없습니다. 이를 데이터 클래스로 정의할 수 있습니다.
데이터 클래스 선언)
data class Question<T>(
val questionText: String,
val answer: T,
val difficulty: Difficulty
)
❗️참고: 데이터 클래스에는 생성자에 매개변수가 하나 이상 있어야 하며 모든 생성자 매개변수는 val 또는 var로 표시되어야 합니다. 데이터 클래스도 abstract 또는 open, sealed, inner일 수 없습니다.
객체를 싱글톤으로 정의하여 객체에는 인스턴스가 하나만 있어야 함을 코드에서 명확하게 전달할 수 있습니다.
개발자가 클래스에 하나의 인스턴스만 생성되길 원하는 경우가 있습니다.
ex)
object StudentProgress {
var total: Int = 10
var answered: Int = 3
}
그중 싱글톤을 companion으로 선언해 클래스 내부에 구현할 수 있습니다. 그렇게 하면 클래스 내부에 있는 자원들을 접근할 수 있습니다.
ex companion)
class Quiz {
val question1 = Question<String>("Quoth the raven ___", "nevermore", Difficulty.MEDIUM)
val question2 = Question<Boolean>("The sky is green. True or false", false, Difficulty.EASY)
val question3 = Question<Int>("How many days are there between full moons?", 28, Difficulty.HARD)
companion object StudentProgress {
var total: Int = 10
var answered: Int = 3
}
}
❗️참고: 싱글톤 객체에는 생성자를 포함할 수 없습니다. 개발자가 인스턴스를 직접 만들 수 없기 때문입니다. 대신 모든 속성이 중괄호 안에 정의되며 초깃값이 부여됩니다.
Kotlin 언어의 기능을 통해 다른 개발자는 기존 데이터 유형을 확장하여 해당 데이터 유형의 일부인 것처럼 점 문법으로 액세스할 수 있는 속성과 메서드를 추가할 수 있습니다
ex)
fun main() {
Quiz.printProgressBar()
}
// 확장 함수 추가
fun Quiz.StudentProgress.printProgressBar() {
repeat(Quiz.answered) { print("▓") }
repeat(Quiz.total - Quiz.answered) { print("▒") }
println()
println(Quiz.progressText)
}
// 확장 속성 추가
val Quiz.StudentProgress.progressText: String
get() = "$answered of $total answered"
//싱글톤 객체(companion)
class Quiz {
companion object StudentProgress {
var total: Int = 10
var answered: Int = 3
}
}
package com.example.javapractice
fun main() {
val question1 = Question<String>("Quoth the raven ___", "nevermore", Difficulty.MEDIUM)
val question2 = Question<Boolean>("The sky is green. True or false", false, Difficulty.EASY)
val question3 =
Question<Int>("How many days are there between full moons?", 28, Difficulty.HARD)
Quiz().apply {
printQuiz()
}
}
//data 클래스
data class Question<T>(
val questionText: String,
val answer: T,
val difficulty: Difficulty
)
//eum 클래스
enum class Difficulty {
EASY, MEDIUM, HARD
}
// 확장 속성 추가
val Quiz.StudentProgress.progressText: String
get() = "$answered of $total answered"
// 확장 함수 추가
fun Quiz.StudentProgress.printProgressBar() {
repeat(Quiz.answered) { print("▓") }
repeat(Quiz.total - Quiz.answered) { print("▒") }
println()
println(Quiz.progressText)
}
//싱글톤 객체(companion)
class Quiz {
val question1 = Question<String>("Quoth the raven ___", "nevermore", Difficulty.MEDIUM)
val question2 = Question<Boolean>("The sky is green. True or false", false, Difficulty.EASY)
val question3 =
Question<Int>("How many days are there between full moons?", 28, Difficulty.HARD)
fun printQuiz() {
question1.let {
println(it.questionText)
println(it.answer)
println(it.difficulty)
}
println()
question2.let {
println(it.questionText)
println(it.answer)
println(it.difficulty)
}
println()
question3.let {
println(it.questionText)
println(it.answer)
println(it.difficulty)
}
println()
}
companion object StudentProgress {
var total: Int = 10
var answered: Int = 3
}
}