kotlin의 for문은 python과 유하게 이터레이터에 의해 배열이나 특정 값의 범위, 컬렉션으로 불리는 요소등에서 사용할 수 있다.
for (요소 변수 in 컬렉션 또는 범위) { 반복할 본문 }
for (i in 5 downTo 1) print(i)
for(i in 1..5 step 2) print(i)
for(i in 5 downTo 1 step 2) print(i)
while, do-while은 다른 언어와 비슷하다.
흐름 제어문
예외 처리문
주의점
1. return문을 생략하거나 return후 변수를 입력하지 않으면 코틀린 컴파일러는 Unit을 반환하는 것을 가정한다.
2. inline으로 선언되지 않은 람다식에서는 return을 그냥 사용할 수 없다. 람다식 앞에 라벨이름@과 같이 사용할 수 있다.위의 retFunc()에서 return을 만나면 함수 자체를 빠져나가 end of retFunc가 출력되지 않지만 아래의 retFunc2()는 라벨과 함께 사용하여 람다식만 빠져나가므로 end of retFunc가 실행된다.
3. 암묵적 라벨
라벨이름@을 붙이지 않으면 람다식의 명칭 그대로 사용된다.
4. 람다식 대신 익명함수를 넣을 수도있다. -> 보통 썼던 방식
5. break와 continue에 라벨을 사용하여 중단하는 위치를 임의로 만들수 있다.
fun labelBreak(){
println("labelBreak")
first@ for(i in 1..5){
second@ for(j in 1..5){
if (j==3) break@first
println("i:$i, j:$j")
}
println("after for j")
}
println("after for i")
}
클래스 : 분류, 범주
프로퍼티: 속성, 변수, 필드, 데이터
메서드 : 함수, 동작, 행동
객체 : 인스턴스
부생성자
주생성자
프로퍼티를 포함한 주생성자
객체를 생성할때 변수 초기화 이외에 코드를 실행해야할때. 주생성자 안에서는 코드를 넣을 수 없으므로 그때는 init
을 사용하여야 한다.
프로퍼티의 기본값 지정도 가능
class Bird(var name: String = "Noname")
상속
open이라는 키워드를 사용하여 상속가능한 class라는 것을 선언해주어야한다. 상속받을 때는 : 기본클래스
형태로 받아올 수 있다.
다형성
open class Bird { // open은 상속 가능을 나타냄
...
fun fly() {...} // 1. 최종 메서드로 오버라이딩 불가
open fun sing() {...} // 2. sing() 매서드는 하위 클래스에서 오버라이딩 가능
}
class Lark() : Bird() { // 하위 클래스
fun fly() { /* 재정의 */ } // 오류! 상위 메서드에서 open 키워드가 없어 오버라이딩 불가
override fun sing() { /* 구현부를 새롭게 재정의 */ } // 3. 구현부를 새롭게 작성
}
// 아예 오버라이딩을 막고자 할때
open class Lark() : Bird() {
final override fun sing() {} // 하위 클래스에서 재정의를 막음
}
super: 상위 클래스 참조
this: 현재 클래스 참조
this와 super를 사용하는 부 생성자
주 생성자와 부 생성자 함께 사용하기
this가 주 생성자를 가리킨다.
1번 부 생성자에서 2번 주 생성자를 호출하고 3번 프로퍼티 할당 -> 4번 초기화 블록 -> 5번 부 생성자의 본문을 차례로 실행.
클래스를 선언할 때 클래스 안에 다시 클래스를 선언(이너 클래스)하는 것이 가능하다. 만일 이너 클래스에서 바깥 클래스의 상위 클래스를 호출하려면 super 키워드와 함께 @ 기호 옆에 바깥 클래스 이름을 작성한다.
이너 클래스에서 바깥 클래스 접근하기
인터페이스 참조하기
앵글 브래킷을 사용한 이름 중복 해결하기
3번처럼 중복되지 않은 경우는 그냥 사용할 수 있으나 중복된 경우 <>를 사용해주어야한다.
private
protected
최상위 선언된 요소에는 지정할 수 없고 클래스나 인터페이스와 같은 요소의 멤버에만 지정할 수 있다.
internal
프로젝트 단위의 모듈이 같으면 접근 할 수 있다.
public
모든 접근 허용
자동차와 도둑의 예제
package chap05.section5.burglar
open class Car protected constructor(_year: Int, _model: String, _power: String, _wheel: String) { // 1
private var year: Int = _year
public var model: String = _model
protected open var power: String = _power
internal var wheel: String = _wheel
protected fun start(key: Boolean){
if (key) println("Start the Engine!")
}
class Driver(_name: String, _license: String){
private var name: String = _name
var license: String = _license
internal fun driving() = println("[Driver] Driving() - $name")
}
}
class Tico(_year: Int, _model: String, _power: String, _wheel: String,
var name: String, private var key: Boolean) : Car(_year, _model, _power, _wheel) {
override var power: String = "50hp"
val driver = Driver(name,"first class")
constructor(_name: String, _key: Boolean) : this(2014, "basic", "100hp","normal",_name,_key){
name = _name
key = _key
}
fun access(password: String){
if (password == "gotico"){
println("----[Tico] access()----")
// super.year // 3. private접근 분가
println("super.model = ${super.model}") // public
println("super.model = ${super.power}") // protected
println("super.model = ${super.wheel}") // internal
super.start(key) // protected
// dirver.name //private 접근 불가
println("Driver().license = ${driver.license}") // public
driver.driving() // internal
} else {
println("You're a burlgar")
}
} }
class Burglar() {
fun steal(anycar: Any){
if (anycar is Tico) {// 4. 인자가 Tico 객체일 때
println("---[Burglar] steal()---")
// println(anycar.power) //protected 접근 불가
// println(anycar.year) // private 접근 불가
println("anycar.name = ${anycar.name}") // public 접근
println("anycar.wheel = ${anycar.wheel}") // internal 접근
println("anycar.model = ${anycar.model}") // public 접근
println(anycar.driver.license) // public 접근
anycar.driver.driving() // internal 접근
// println(Car.start()) // protected 접근 불가
anycar.access("dontknow")
} else {
println("Nothing to steal")
}
}
}
fun main() {
// val car = Car() // protected 생성 불가
val tico = Tico("kildong", true)
tico.access("gotico")
val burglar = Burglar()
burglar.steal(tico)
}
java와 다르게 kotlin은 주생성자를 만드는 방식에서
class User(val id: Int, var name: String, var age: Int)
와 같이 써주면 자동으로 getter, setter가 만들어진다. 나중에 접근하여
val name = user.name
user.age = 41
과 같은 형태로 써도 이건 코틀린 내부적으로 접근 메서드가 내장되어 있는 것이다.
var 프로퍼티 이름[: 프로퍼티 자료형][=프로퍼티 초기화]
[get() {게터 본문}]
[set(value) {세터 본문}]
val은 게터만
특수한 변수
만일 보안 때문에 외부에서 name에 접근해서 사용하지 못하게 하려면 가시성 지시자를 넣을 수 있다.
var name: String = _name
private set()...
이럼 외부에서 객체 생성 후 user.name = "test"와 같이 값을 재할당하는 것이 금지된다.