Kotlin_03

김재현·2023년 3월 24일
0

반복문

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은 다른 언어와 비슷하다.


흐름 제어문

  • return
  • break
  • continue

예외 처리문

  • try{...} catch{...}
  • try{...} catch{...} finally{...}

주의점
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")
}

  • throw로 임의로 에러를 발생시킬 수 있다.
  • 사용자 정의 예외를 만들어서 처리할 수 있다.

객체 지향 프로그래밍

  • 프로그램의 구조를 객체 간 상호작용으로서 표현하는 프로그래밍 방식.

클래스 : 분류, 범주
프로퍼티: 속성, 변수, 필드, 데이터
메서드 : 함수, 동작, 행동
객체 : 인스턴스

생성자

  • 주 생성자와 부 생성자로 나뉜다.

부생성자

주생성자

프로퍼티를 포함한 주생성자

  • 객체를 생성할때 변수 초기화 이외에 코드를 실행해야할때. 주생성자 안에서는 코드를 넣을 수 없으므로 그때는 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: 이 요소는 외부에서 접근할 수 없다.
  • public : 이 요소는 어디서든 접근이 가능하다.(기본값)
  • protected : 외부에서 접근할 수 없으나 하위 상속 요소에서는 가능하다.
  • internal : 같은 정의의 모듈 내부에서는 접근이 가능하다.
  1. private

  2. protected
    최상위 선언된 요소에는 지정할 수 없고 클래스나 인터페이스와 같은 요소의 멤버에만 지정할 수 있다.

  3. internal
    프로젝트 단위의 모듈이 같으면 접근 할 수 있다.

  4. 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)
}

클래스와 클래스의 관계

  1. 연관 관계
  • 2개의 서로 분리된 클래스가 연결을 가지는 것. 단방향 혹은 양방향으로 연결 될 수 있다.
  • 두 요소가 서로 다른 생명주기를 가지고 있다.
  1. 의존 관계
  • 한 클래스가 다른 클래스에 의존되어 있어 영향을 주는 경우
  • ex) Doctor 클래스를 생성하려는데 변수에 Patient의 객체가 필요한 경우. Doctor는 Patient의 객체에 의존하는 관계가 된다.
  1. 집합 관계
  • 연관 관계와 거의 동일하지만 특정 객체를 소유한다는 개념이 추가된 것.
  • ex) 오리가 특정 연못을 주거지로 삼는다면 연못이 오리를 소유할 수 있는 것.
  1. 구성 관계
  • 집합 관계와 거의 동일하지만 특정 클래스가 어느 한 클래스의 부분이 되는 것.
  • 구성품으로 지정된 클래스는 생명주기가 소유자 클래스에 의존되어 있다.

chap6. 프로퍼티와 초기화

프로퍼티의 접근

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은 게터만

특수한 변수

  • value: 세터의 매개변수로 외부로부터 값을 가져옴(이름 변경 가능)
  • field: 프로퍼티를 참조하는 변수(이름 변경 불가)

커스텀 게터와 세터의 사용

만일 보안 때문에 외부에서 name에 접근해서 사용하지 못하게 하려면 가시성 지시자를 넣을 수 있다.

var name: String = _name
	private set()...

이럼 외부에서 객체 생성 후 user.name = "test"와 같이 값을 재할당하는 것이 금지된다.

profile
배운거 정리하기

0개의 댓글