for(요소 in 리스트)
for(인덱스 in 시작값 until 마지막값)
for(인덱스 in 시작값 ... 마지막값)
0 until 9 : 0 <= x < 9
0 .. 9 : 0 <= x <= 9
while(조건식){
로직
증감식
}
break
가장 가까운 반복문에서 탈출하고 다음 블록으로 간다.
continue
continue 이후의 코드는 실행하지 않고 반복문의 다음 인덱스가 실행된다.
arrayOf() : 배열을 만들어주는 함수
var infos = arrayOf("꿩","닭","참색","오목눈이","공작새") 로 배열을 만들 수 있다.
fun 메소드이름( 자료형 : 변수명, ... ) : 반환되는 값의 자료형 {
...
}
만약 함수에 반환되는게 없다면 반환자료형을 생략하거나 Unit을 쓰면 된다.
코틀린은 모든것이 클래스형태이므로 객체화할 수 있다.
클래스는 정보(프로퍼티)와 행위(메소드)를 가진다.
OOP의 5대 키워드 : 상속, 캡슐화, 추상화, 클래스, 다형성
class 클래스이름 {
정보1
정보2
행위1
행위2
}
프로퍼티만 가진 클래스다.
data class 키워드를 사용해 만듬.
아래와 같은 유용한 메소드를 자동으로 만들어줌.
hashCode(): 객체를 구분하기 위한 고유값을 리턴해줘요
eauals(): 동일한 객체인지 비교해서 true 또는 false를 리턴해줘요
copy(): 현재 객체의 모든 정보를 복사해서 새로운 객체를 리턴해줘요
toString(): 현재 객체의 모든 정보(프로퍼티)를 예쁘게 출력해줘요
getXXX()/setXXX(매개변수): 변수의 값을 리턴하거나 설정해줘요
클래스 상속과 관련된 개념임
상속받을 자식클래스를 미리 정의 가능
무분별한 상속을 방지할 수 있다.
컴파일 시점에 생성할 수 있는 자식을 알 수 있기에 효율적인 다형성 구현 가능하다.
sealed class 부모클래스 {
class 자식클래스1 : 부모클래스생성자
class 자식클래스2 : 부모클래스생성자
}
자바의 static 대신 사용하는 키워드다.
클래스를 만들었다고 해서 프로그램 메모리에 바로 올라가는게 아닌데 object를 클래스 앞에 붙이면 바로 메모리에 적재되어 객체를 만들지 않아도 바로 사용가능하다.
기본 생성자
명시적 생성자 ( 주 생성자와 부 생성자로 구성)
init {
println("매개변수없는 생성자 실행 완료!")
// 항상 클래스가 생성될때 이 코드가 실행됨.
}
constructor(_name:String, _hairColor:String, _height:Double) {
println("${_name}을 생성자로 넘겼어요")
println("${_hairColor}를 생성자로 넘겼어요")
println("${_height}를 생성자로 넘겼어요")
}
코틀린에서는 생략된 final키워드로 상속을 막아두고 있다.
그래서 상속을 활성화하기 위해선 클래스 앞에 open 키워드를 활용해 상속 관계를 만들 수 있다.
상속을 이용하면 부모클래스만 변경하는것으로 코드의 재사용성을 높일 수 있다.
부모 클래스에서 생성자를 받는다면 자식 클래스에서도 파라메터로 생성자를 넣어야한다.
open class Bird{
fun fly(){
println("새~가 날아~간~다~")
}
}
}
class Chicken : Bird() { }
class Duck : Bird() { }
fun main(){
var bird = Bird()
var chicken = Chicken()
var duck = Duck()
chicken.fly()
duck.fly()
}
부모 클래스의 프로퍼티(정보)나 메소드(행위)를 재설계할 수 있다.
주로 부모 클래스의 메소드를 재설계한다.
클래스 앞에 open을 붙이면 다른 클래스에서 상속이 가능하다.
메소드 앞에 open을 붙이면 자식 클래스에서 오버라이딩 가능하다.
오버라이딩 단축어 : Ctrl + O
동일한 이름의 메소드를 여러개 만들수 있는것을 말한다.
다 되는건 아니고 매개변수의 갯수, 자료형을 달리 하면 가능하다.
반환형의 차이는 해당사항이 없다.
정수를 더하는 add라는 메소드를 만들었다.
그런데 실수도 더하고 싶은데 이미 add가 있어서 만들수없다. 그렇다고 addInt(), addDouble()이렇게 만들자니 영 맘에 안든다. 이럴때 오버로딩을 이용해 매개변수의 자료형만 달리해서 같은 이름 add()로 만들 수 있다.
인터페이스는 추상메소드(로직을 구현하지 않은 메소드)로 구성하는게 근본이긴하나 최근엔 로직을 구현하는것도 가능하다곤 한다.
코틀린에서는 부모클래스는 오직 한개라 모두 상속으로 처리할 수 없다. 따라서 근본적인 공통점은 상속받고, 추가적인 기능은 인터페이스로 추가하면 된다.
interface 인터페이스이름 {
fun 메소드이름()
}
class Duck(name: String) : Bird(name), WaterBirdBehavior {
override fun swim() {
println("${name}가 수영해요~")
}
}
try{
예외가 발생할 것 같은 코드
} catch(예외 종류){
예외발생 시 실행할 코드
}
while(true) {
try {
var num1 = readLine()!!.toInt()
println("내가 입력한 숫자는 ${num1}입니다")
break
} catch(e:java.lang.NumberFormatException) {
println("숫자를 입력하세요")
}
}
try{
예외가 발생할 것 같은 코드
} catch(예외 종류){
예외발생 시 실행할 코드
}
finally{
예외가 발생 안해도, 발생해도 항상 실행하는 코드.
}
while(true) {
try {
var num1 = readLine()!!.toInt()
println("내가 입력한 숫자는 ${num1}입니다")
break
} catch(e:java.lang.NumberFormatException) {
println("숫자를 입력하세요")
} finally {
println("키보드와의 연결은 정상적입니다")
}
}
안정성을 위해 코틀린에선 변수를 선언하고 초기화를 해줘야하나 나중에 초기화를 해줘도 된다. 그것을 지연초기화(늦은 초기화)
라고 한다.
-> 지연초기화를 사용하는 궁극적인 이유는 저사양 환경에서 사용할 때 값을 대입해 메모리를 효율적으로 사용하기 위함이다.
var agent:String = " "
lateinit var agent:String
상수
lazy 키워드 사용
상수를 사용하는 시점에 값을 대입하고 초기화 됨
val address:String by lazy
isInitialized
값이 초기화되었는지 확인할 수 있다.
값이 아니라 참조형태이기에 this:: 또는 ::이 붙는다.
if(this::name.isInitialized)
Null 예외는 프로그램이 실행도중 꺼질 수 있는 치명적인 오류
그래서 코틀린은 Null 예외로부터 벗어나기 위해 자료형에 Null을 가질수있는지 여부를 명시할 수 있다.
코틀린은 ?, !!, ?., ?:를 사용해 Null 예외로부터 벗어날려 한다.
강제로 Null이 아니라는 !!는 최대한 사용을 지양하자.
? : null이 저장될수 도 있다.
ex) var address:String? = null
!! : null이 아님을 강제로 보장 (권장X)
?. : null이 아닐때만 참조해줌, null일 때는 null이란 문자열이 그대로 출력( safe-calls 연산자, 안전 호출 연산자)
?: : ?. 에서 null일 경우 null이 그대로 출력된다. 다만 null이 출력되는게 보기 싫어 null대신 다른 문자열로 출력하고 싶을때 사용한다. (엘비스 연산자)
내장 메소드 arrayOf() 사용
var arr = arrayOf("1","5","8")
println(Arrays.toString(arr))
//[1, 5, 8]
Arrays.toString(배열명) 으로 배열 안에 든 값 출력
withIndex()와 함께 쓰면 배열의 인덱스와 값을 동시에 출력 가능하다.
fun main() {
var kors = arrayOf(90, 94, 96)
for((idx, kor) in kors.withIndex()) {
println("${idx}번째 국어 점수는 ${kor}입니다")
}
}
0번째 점수는 90입니다.
1번째 점수는 94입니다.
2번째 점수는 96입니다.
소중한 정보 감사드립니다!