MainActivity.kt 코드 파일 알아보기
package com.example.helloworld
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
변수와 상수
val pi: Double = 3.14 //val 변수명: 자료형 = 값
val name = "gil-dong" //형추론 (String)
var age = 21 //형추론 (Int)
age = 25 //재할당
기본 자료형
val numByte: Byte = 100
val numShort: Short = 20
val numInt: Int = 1
val numLong: Long = 2L
val numDouble: Double = 3.2
val numFloat: Float = 3.2f
val char1: Char = 'H'
val string1: String = "Hi, This is String"
val isTrue: Boolean = true
val stringArray: Array<String> = arrayOf("apple", "banana", "grape")
val intArray: Array<Int> = arrayOf(1, 2, 3)
println(stringArray[0])//apple
println(stringInt[2])//3
함수
fun printAge(age: Int): Unit {
println(age)
}
fun printAge(age: Int) {//Unit 생략
println(age)
}
fun addNum(a : Int, b : Int) : Int {
return a + b
}
fun minusNum(a : Int, b : Int) = a - b
println(minusNum(minusNUm(1000, 200), 100))//700
문자열 템플릿
val price = 3000
val tax = 300
val originalPrice = "The original price is $price"
val totalPrice = "The total price is ${price + tax}"
범위 클래스
범위 클래스로 특정 범위의 값들을 간편하게 표현할 수 있다. 범위 클래스로는 IntRange, LongRange, CharRange 등이 있다.
숫자의 범위
val numRange : IntRange = 1..5
println(numRange.contains(3)) //true
println(numRange.contains(10)) //false
val charRange : CharRange = 'a'..'e'
println(charRange.contains('b'))//true
println(charRange.contains('z'))//false
for문
for (i in 1..5) {
println(i) //1, 2, 3, 4, 5
}
for (i in 5 down to 1) {
println(i) //5, 4, 3, 2, 1
}
for (i in 1..10 step 2) {
println(i) //1, 3, 5, 7, 9
}
val students = arrayOf("jun-gi", "jun-su", "yeon-seo", "jun-seo")
for (name in students) {
println(name) //jun-gi, jun-su, yeon-seo, jun-seo
}
val students = arrayOf("jun-gi", "jun-su", "yeon-seo", "jun-seo")
for ((index, name) in studetns.withIndex()) {
println("Index: $index Name : $name")
}
while문
var num = 1
while (num < 5) {
println(num)
num++
}
var num = 1
do {
num++
println(num)
} while (num < 5)
if문
val examScore = 60
val isPass = false
if (examScore > 80) {
isPass = true
}
println("시험 결과 : $isPass")
when문
val weather = 15
when (weather) {
-20 -> {println("매우 추운 날씨")}//값 하나
11, 12, 13, 14 -> {println("쌀쌀한 날씨")}//값 여러 개
in 15..26 -> {println("활동하기 좋은 날씨")}//범위 안에 들어가는 경우
//범위 안에 안 들어가는 경우
!in -30..50 -> {println("잘못된 값입니다. -30 ~ 50 가운데 값을 적어주세요")}
else -> {println("잘 모르겠는 값")}//위 경우가 모두 아닐 때
}
val essayScore = 95
val grade = when(essayScore) {
in 0..40 -> "D"
in 41..70 -> "C"
in 71..90 -> "B"
else -> "A"
}
println("에세이 학점 : $grade")
리스트
val numImmutableList = listOf(1, 2, 3)
numImmutableList[0] = 1//읽기 모드이므로 오류 발생
val numMutableList = mutableListOf(1, 2, 3)
numMutableList[0] = 100
println(numMutableList)//[100, 2, 3]
println(numMutableList[0])//100
val numMutableList = mutableListOf(1, 2, 3)
numMutableList[0] = 100
println(numMutableList.contains(5))//false
셋(Set)
//일기 전용 셋
val immutableSet = setOf(1,1,2,2,3,3,3)
println(immutableSet)
//읽기 쓰기 전용 셋
val mutableSet = mutableSetOf(1,2,3,3,3,3)
mutableSet.add(100)
mutableSet.remove(1)
mutableSet.remove(200)
println(mutableSet)
println(mutableSet.contains(1))
맵(Map)
//읽기 전용 맵
val immutableMap = mapOf("name" to "junsu", "age" to 13, "age" to 15, "height" to 160)
println(immutableMap)//{name=junsu, age=15, height=160}, 키를 중복으로 정의하면 나중에 정의한 것을 기준으로 저장됨
//읽기 쓰기 모두 가능한 맵
val mutableMap = mutableMapOf("돈까스" to "일식", "짜장면" to "중식", "김치" to "중식")
mutableMap.put("막국수", "한식")
mutableMap.remove("돈까스")
mutableMap.replace("김치", "한식")
println(mutableMap)//{짜장면=중식, 김치=한식, 막국수=한식}
클래스 선언 및 객체 생성
class Car(val color : String)
val car = Car("red")
println("My car color is ${car.color}")
클래스 생성자
주 생성자
class Person(val name : String) {}
보조 생성자
class Person {
constructor(age : Int) {
println("I'm $age years old")
}
}
class Person(name : String) {
constructor(name : String, age : Int) : this(name) {
println("I'm $age years old")
}
}
초기화 블록
class Person(name : String) {
val name : String
init {
if (name.isEmpty()) {//매개변수 문자열이 비어 있는 경우 에러 발생
throw IllegalArgumentException("이름이 없어요.")
}
this.name = name//문자열이 안 비어 있으면 이름 저장
}
}
클래스의 상속
open class Flower{
open fun waterFlower() {
println("water flower")
}
}
class Rose : Flower() {
override fun waterFlower() {
super.waterFlower()
println("Rose is happy now")
}
}
val rose = Rose()
rose.waterFlower()
open class Flower(val name : String) {}
class Rose(name : String, color : String) : Flower(name) {}
접근 제한자
companion 키워드
class Dinner {
companion object {
val MENU = "pasta"
fun eatDinner() {
println("$MENU is yummy")
}
}
}
println(Dinner.Companion.MENU)
println(Dinner.MENU)
Dinner.eatDinner()
추상 클래스
abstract class Game {
fun startGame() {
println("게임을 시작했습니다.")
}
abstract fun printName()
}
class Overwatch : Game() {
override fun printName() {
println("오버워치입니다.")
}
}
val overwatch = Overwatch()
overwatch.startGame()//Game 클래스 메소드
overwatch.printName()//Overwatch 클래스 메소드
데이터 클래스
data class Memo(val title : String, val content : String, var isDone : Boolean)
var memo1 = Memo("마트 가기", "계란, 우유, 빵", false)
var memo2 = memo1.copy(content = "칫솔, 과자")
println(memo1.toString())
println(memo2.toString())
인터페이스 정의
interface Car{
abstract fun drive()
fun stop()
}
디폴트 메소드
interface Car{
abstract fun drive()
fun stop()
fun destroy() = println("차가 파괴되었습니다.")
}
인터페이스 구현
interface Car{
abstract fun drive()
fun stop()
fun destroy() = println("차가 파괴되었습니다.")//디폴트 메소드
}
class Ferrari : Car {
override fun drive() {
println("페라리가 달립니다.")
}
override fun stop() {
println("페라리가 멈춥니다.")
}
}
val myFerrari = Ferrari()
myFerrari.drive()
myFerrari.stop()
myFerrari.destroy()
클래스 상속과 인터페이스 구현
interface Animal {
fun breath()
fun eat()
}
interface Human{
fun think()
}
open class Name(val name : String) {
fun printName() {
println("제 이름은 $name")
}
}
class Korean(name : String) : Name(name), Animal, Human {
override fun breath() {
println("후-하")
}
override fun eat() {
println("한식 먹기")
}
override fun think() {
println("생각하기")
}
}
val joyce = Korean("정아")
joyce.breath()
joyce.printName()
Null 처리하기
var myName : String// 초기화를 해주지 않아 에러
var myName : String = null//non-nullable 자료형에 null을 넣어서 에러
var myName : String? = null//자료형 뒤에 ?를 붙여서 null이 올 수 있음을 알려주면 된다.
myName
myName = "Joyce"
println(myName.reversed()) // 에러 발생
셰이프 콜 연산자?
fun reversedName(name : String?) : String? {//인수, 반환값 모두 null 가능
return name?.reversed()//name이 null이라면 null 반환
}
println(reversedName("joyce"))//ecyoj
println(reversedName(null))//null
엘비스 연산자 ?:
fun reversedName(name : String?) : String? {
return name?.reversed() ?: "이름을 확인해주세요."
}
println(reversedName("joyce"))
println(reversedName(null))
확정 연산자 !!
fun reversedName(name : String?) : String {//반환 자료형 null 불가능
return name!!.reversed() //절대 null이 아님을 보증
}
println(reversedName("joyce"))
lateinit 키워드
lateinit var lunch : String
lunch = "waffle"
lazy 키워드
람다식
val sayHello = fun() {println("안녕하세요.")}
sayHello()
람다식 정의
val squareNum : (Int) -> (Int) = {number -> number * number}
println(squareNum(12))//144

val squareNum2 = {number : Int -> number * number}
val squareNum3 : (Int) -> (Int) = {it * it}
람다를 표현하는 다양한 방법
fun invokeLambda (lambda : (Int) -> Boolean) : Boolean {//람다를 인수로 받음
return lambda(5)
}
val paramLambda : (Int) -> Boolean = {num -> num == 10}
println(invokeLambda(paramLambda))//람다식의 인수로 넣은 5 != 10이므로 false
invokeLambda({num -> num == 10})//람다식 바로 넣어주기
invokeLambda({it == 10})//인수가 하나일 때 it으로 변경 가능
invokeLambda() {it == 10} //만약 함수의 마지막 인수가 람다일 경우 밖으로 뺄 수 있음
invokeLambda{it == 10}//그 외 인수가 없을 때 () 생략 가능
SAM(Single Abstract Method) 변환
button.setOnClickListener{
//버튼이 눌렸을 때 작동할 코드
}