Kotlin Playground: Edit, Run, Share Kotlin Code Online
play.kotlinlang.org
온라인 컴파일러
https://play.kotlinlang.org/byExample/04_functional/01_Higher-Order%20Functions
Kotlin Playground: Edit, Run, Share Kotlin Code Online
play.kotlinlang.org
참고
Basic 문법
// package my.demo
// import kotlin.text.*
const val MY_CONSTANT = 10
fun main() {
run {
println("Hello, world!!!")
val bb:String = "bbb"
val `aa` = 1
println(aa)
println("bb : ${bb}" + " << ")
// aa를 문자열로 변환
val cc = aa.toString()
println(cc)
// 변수의 타입을 출력
println("Type of aa: ${cc::class.simpleName}")
val x = 0
val y = 0
val hasErrors = false;
val testPassed = true;
println(( x == 1 ) or ( y == 1 )) // false
println(( x == 0 ) || ( y == 0 )) // true
println(( x == 1 ) and ( y != 1 )) // false
println(( x == 1 ) and ( y == 1 )) // false
println(( x == 1 ) xor ( y == 1 )) // false
println(( x == 1 ) xor ( y != 1 )) // true
println( x == 1 || y / (x - 1) != 1) // true
println( x != 1 && y / (x - 1) != 1) // true
println("------------------------------------")
val a = "Hello"
val b = "Hello"
val c = a
println(a == b) // true, 값이 같음
println(a === b) // true, <- JVM 최적화가 원인
println(a === c) // true, 같은 객체 참조
data class Person(val name: String)
/*
* data class를 사용시, 자동으로 equals, hashCode, toString 메서드를 생성
* */
val person1 = Person("Alice")
val person2 = Person("Alice")
val person3 = person1
println(person1 == person2) // true, 값이 같음 (Class 의 equals 메소드 동작)
println(person1 === person2) // false, 서로 다른 객체
println(person1 === person3) // true, 같은 객체 참조
val s = "Hello! "
println(s[0]) // H
println(s[1]) // e
println(s[5]) // !
val q = emptyArray<String>() // Array<String> (원소 0개)
val w = arrayOf("Hello", "World") // Array<String> (원소 2개)
val e = arrayOf(1, 4, 9) // Array<Int> (원소 3개)
println("------------------------------------")
val squares = arrayOf( 1, 4, 9, 16 )
squares.size // 4
squares.lastIndex // 3
squares[3] // 16
squares[1] // 4
val numbersValueCopy = squares.copyOf()
println(numbersValueCopy == squares) // false
println(numbersValueCopy === squares) // false
println(numbersValueCopy.contentEquals(squares)) // true
val numbersReference = squares
println(numbersReference == squares) // true
val xx = intArrayOf(1, 2, 3) + 4 + 5 // 원소를 하나만 추가 : 1, 2, 3, 4, 5
val yy = intArrayOf(1, 2, 3) + intArrayOf(4, 5) // 다른 배열을 추가 : 1, 2, 3, 5, 6
println(xx == yy) // false
println(xx.contentEquals(yy)) // true
}
println("EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE")
run{
fun sum(a: Int, b: Int): Int {
return a + b
}
fun sumLambda(a: Int, b: Int): Int = a + b
fun printSum(a: Int, b: Int): Unit {
println("sum of $a and $b is ${a + b}")
}
class Rectangle(val height: Double, val length: Double) {
val perimeter = (height + length) * 2
}
val rectangle = Rectangle(5.0, 2.0)
println("The perimeter is ${rectangle.perimeter}")
val a = 1
val b = 2
val c = if (a > b) a else b
println("------------------------------------")
val items_for = listOf("apple", "banana", "kiwifruit")
for (item in items_for) {
println(item)
}
val items_while = listOf("apple", "banana", "kiwifruit")
var index = 0
while (index < items_while.size) {
println("item at $index is ${items_while[index]}")
index++
}
fun describe(obj: Any): String =
when (obj) {
// 조건문 -> 리턴 값
1 -> "One"
"Hello" -> "Greeting"
is Long -> "Long"
!is String -> "Not a string"
else -> "Unknown"
}
println(describe(1))
println(describe("Hello"))
println(describe(listOf(1,2,3)))
println(2)
for (x in 1..3) {
println("for - ${x}")
}
println("------------------------------------")
val check_list = listOf(1,2,3,4,5)
if (2 in check_list) {
println("check_list - ${2}")
}
if (5 in check_list) println("check_list - ${5}")
println("+++++++++++++++++++++++++++++++++++++++")
println(check_list == null) // f
println(check_list is List) // t
println(check_list.filter { check_list -> check_list > 3 })
// val map = mapOf("a" to 1, "b" to 2, "c" to 3)
// println(map["a"])
// map["a"] = 99
// println(map)
val map = mutableMapOf("a" to 1, "b" to 2, "c" to 3)
println(map["a"]) // 1 출력
map["a"] = 99
println(map) // {a=99, b=2, c=3} 출력
val constMap = mapOf("a" to 1, "b" to 2, "c" to 3)
println(constMap["a"])
// constMap["a"] = 99 수정 불가능
println(constMap) // {a=1, b=2, c=3} 출력
println("+++++++++++++++++++++++++++++++++++++++")
}
}
Class 문법
/* 문법 정리 */
/*
* 추상클래스
* 멤버변수 클래스변수
* 생성자
* 오버라이딩
* 오버로딩
* 디폴트 매개변수
* */
// 추상 클래스 정의
abstract class Animal(val name: String) {
abstract fun makeSound()
fun introduce() {
println("-----------")
}
}
// 상속을 통해 구체적인 클래스 정의
class Dog(name: String) : Animal(name) {
// 멤버 변수
var memberValue: String = "멤버 변수"
// 클래스 변수 (모든 인스턴스가 공유)
companion object {
var classValue: Int = 55
}
// this , Type 체크
fun getMemberValueType(): String {
return this.memberValue::class.simpleName ?: "Unknown"
}
// this , Type 체크
fun getClassValueType(): String {
return classValue::class.simpleName ?: "Unknown"
}
// 오버 라이딩
override fun makeSound() {
println("멍멍!")
}
// 오버 로딩
fun overLoadingFunc():String{
return "오버로딩 : 1"
}
// 오버 로딩
fun overLoadingFunc(tt: Int):String{
return "오버로딩 : $tt"
}
// 오버 로딩
fun overLoadingFunc(tt: String):String{
return "오버로딩 : $tt"
}
//디폴트 매개 변수
fun greet(greeting: String = "Hello") {
println("$greeting, $name!")
}
}
class Cat(name: String) : Animal(name) {
override fun makeSound() {
println("야옹!")
}
}
fun main() {
// try-catch 표현식
try {
val number = "123a".toInt() // 숫자로 변환 시도
} catch (e: NumberFormatException) {
println("예외 발생: ${e.message}")
}
// apply 함수 사용
val dog = Dog("바둑이").apply {
introduce()
// makeSound()
}
dog.makeSound()
val cat = Cat("나비").apply {
introduce()
makeSound()
}
val test = Dog("니다")
println(test.overLoadingFunc())
println(test.overLoadingFunc(999))
println(test.overLoadingFunc("a"))
// Getter
println(test.memberValue)
// Setter
dog.memberValue = "새로운 멤버 변수 값"
println(test.memberValue)
// Class value getter
println(Dog.classValue)
// this , Type 체크
println(test.getMemberValueType())
println(test.getClassValueType())
test.greet() // 디폴트 인사 사용: "Hello, Alice!
test.greet("Hi") // 사용자 정의 인사: "Hi, Alice!
}
Special Class, Functional
/* 문법 */
/*
* lambda
* Higher-Order Func
* Data Classes
* Enum Classes
* Sealed Classes
* Object Keyword
* */
// 람다 함수 (Lambda Function)
// 람다 함수는 익명 함수로, 간단한 연산이나 콜백을 정의할 때 주로 사용됩니다.
// 함수형 프로그래밍 스타일을 지원하며, 코드의 간결성을 높여줍니다.
val sum = { a: Int, b: Int -> a + b }
// 고차 함수 (Higher-Order Functions)
// 고차 함수는 함수를 인자로 받거나 함수를 반환하는 함수입니다.
// 코드의 재사용성을 높이고, 함수형 프로그래밍을 가능하게 합니다.
fun operate(a: Int, b: Int, operation: (Int, Int) -> Int): Int {
return operation(a, b)
}
// 데이터 클래스 (Data Classes)
// 데이터 클래스는 주로 데이터를 저장하는 데 사용됩니다.
// 자동으로 equals(), hashCode(), toString() 등의 메서드를 생성하여 편리합니다.
// 불변 객체를 만들 때 주로 사용됩니다.
data class User(val name: String, val age: Int)
// 열거형 클래스 (Enum Classes)
// 열거형 클래스는 상수들을 정의할 때 사용됩니다.
// 각 상수는 고유한 객체이며, 주로 상태나 방향 등을 나타낼 때 사용됩니다.
enum class Direction {
NORTH, SOUTH, EAST, WEST
}
// 봉인된 클래스 (Sealed Classes)
// 봉인된 클래스는 클래스 계층을 제한할 때 사용됩니다.
// ** 모든 하위 클래스가 미리 정의되어야 하는 경우에 사용 **
// 주로 when 표현식과 함께 사용하여 타입의 안전성을 높입니다.
// 상속 가능한 클래스의 종류를 제한하여 의도하지 않은 확장을 방지합니다.
sealed class Result // 상위,부모클래스
data class Success(val data: String) : Result()
data class Error(val message: String) : Result()
fun handleResult(result: Result) {
when (result) {
is Success -> println("Success: ${result.data}")
is Error -> println("Error: ${result.message}")
// else 문을 사용하지 않음으로써 새로운 하위 클래스가 추가될 때 경고를 받을 수 있음
}
}
// 객체 키워드 (Object Keyword)
// 객체 키워드는 싱글톤 객체를 정의할 때 사용됩니다.
// 프로그램 내에서 하나의 인스턴스만 필요할 때 사용합니다.
// 주로 유틸리티 클래스나 전역 상태를 관리할 때 사용됩니다.
object Database {
val name = "MainDB"
fun connect() = println("Connected to $name")
}
fun main() {
// 람다 함수 사용 예제
println(sum(3, 4)) // 출력: 7
// 고차 함수 사용 예제
val result = operate(5, 3, { a, b -> a * b })
println(result) // 출력: 8
val funPointer = { a:Int, b:Int -> a * b }
println(operate(1,99,funPointer))
// 데이터 클래스 사용 예제
val user = User("Alice", 30)
println(user) // 출력: User(name=Alice, age=30)
// 열거형 클래스 사용 예제
val dir = Direction.NORTH
println(dir) // 출력: NORTH
println("--------------------------")
val dirs = Direction.values()
for (x in dirs) {
println(x)
}
println("--------------------------")
println(dir.ordinal)
println(Direction.SOUTH.name)
println(Direction.valueOf("EAST"))
println(Direction.values().size)
// 봉인된 클래스 사용 예제
val success = Success("Data loaded")
handleResult(success) // 출력: Success: Data loaded
// 객체 키워드 사용 예제 <- 싱글톤
Database.connect() // 출력: Connected to MainDB
}
Generic Class, Generic Function, Type Bound, 상속과 제네릭
/////////////////////////////////////////////////////////////////////
// 제네릭 클래스를 정의
class Box<T>(paramItem: T) {
var item = paramItem
fun getItemCustom(): T {
return item
}
fun setItemCustom(newItem: T) {
item = newItem
}
}
fun main() {
// Box 클래스에 String 타입을 사용
val stringBox = Box("Hello, Kotlin!")
println(stringBox.getItemCustom()) // 출력: Hello, Kotlin!
// Box 클래스에 Int 타입을 사용
val intBox = Box(123)
println(intBox.item) // 출력: 123
// 클래스 내에서 var 로 자동생성된 프로퍼티의 getter setter를 사용
// 값을 변경
intBox.setItemCustom(456)
println(intBox.getItemCustom()) // 출력: 456
}
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
// 제네릭 함수를 정의
fun <T> printItem(item: T) {
println("Item: $item")
}
// 범용 함수로 정의
fun printParam(par: Any){
println("Param : $par")
}
fun main() {
printItem("Hello, World!") // 출력: Item: Hello, World!
printItem(42) // 출력: Item: 42
printItem(3.14) // 출력: Item: 3.14
printParam("Hello, World!")
printParam(42)
printParam(3.14)
}
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
// 제네릭 타입에 상한 제한을 추가 (Number를 상속받는 타입만 허용)
fun <T : Number> sum(a: T, b: T): Double {
return a.toDouble() + b.toDouble()
}
fun main() {
println(sum(10, 20)) // 출력: 30.0
println(sum(5.5, 3.3)) // 출력: 8.8
// 아래 코드는 컴파일 에러 발생 (String은 Number를 상속받지 않음)
// println(sum("Hello", "World"))
}
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
// 제네릭 인터페이스 정의
interface Repository<T> {
fun save(item: T)
fun findById(id: Int): T?
}
// 제네릭 인터페이스 구현
class StringRepository : Repository<String> {
private val storage = mutableMapOf<Int, String>()
override fun save(item: String) {
val id = storage.size + 1
storage[id] = item
println("Saved: $item with ID: $id")
}
override fun findById(id: Int): String? {
return storage[id]
}
}
fun main() {
val repository = StringRepository()
repository.save("Kotlin")
repository.save("Java")
println(repository.findById(1)) // 출력: Kotlin
println(repository.findById(2)) // 출력: Java
println(repository.findById(9999)) // 출력: null
}
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
// 클래스 상속 및 제네릭(Generic) 사용
class LeDeviceListAdapter : RecyclerView.Adapter<LeDeviceListAdapter.ViewHolder>() {
>>
LeDeviceListAdapter 클래스가
RecyclerView.Adapter 클래스의 파라미터를 "LeDeviceListAdapter.ViewHolder" 타입으로 지정해 생성자를 호출한 인스턴스를
상속한다. ( 타입 === 제네릭 타입 파라미터)
라는 의미 이고
class LeDeviceListAdapter : RecyclerView.Adapter<LeDeviceListAdapter.ViewHolder> {
>>
LeDeviceListAdapter 클래스가
LeDeviceListAdapter.ViewHolder 를 인자값 타입으로 가지는 RecyclerView.Adapter 클래스를
상속한다.
라는 의미이다.
여기서 Tip 은
상속할 부모 클래스에 생성자 파라미터가 있는 경우, 자식 클래스에서 반드시 부모 클래스의 생성자를 호출해 인스턴스를 상속받아야 한다.
반면, 부모 클래스에 생성자 파라미터가 없는 경우에는 부모 클래스의 기본 생성자가 자동으로 호출되므로,
자식 클래스에서 부모 클래스의 생성자를 명시적으로 호출할 필요는 없으며 이는 선택사항이다.
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
'언어 정리 > kotlin, android' 카테고리의 다른 글
BLE 기능 [ Kotlin ] (1) | 2024.11.19 |
---|---|
Webview 기능 [ Kotlin ] (1) | 2024.11.19 |
android studio IDE 단축키 (0) | 2024.11.15 |
댓글