ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 코틀린 기본요소
    Kotlin 2019. 3. 20. 23:24

    함수와 변수

    코틀린에서 타입 선언을 생략해도 된다는 사실과 변경 가능한 데이터와 변경 불가능한 데이터에 대해 알아보자.

    코틀린 문법의 특성

    • 함수를 선언할대 fun키워드를 사용한다.
    • 파라미터 이름 뒤에 그 파라이머의 타입을 쓴다. 나중에 보면 축약문을 많이 쓰게 되는데 타입은 축약할 수 있어도 변수명 또는 파라미터명은 생략할 수 없지 않은가?
    • 함수를 최상위 수준에 정의할 수 있다. 자바처럼 반드시 클래스 안에 함수를 정의할 필요는 없다.
    • 배열도 ㅇ리반적인 클래스와 마찬가지다. 코틀린에는 배열 처리를 위한 문법이 따로 존재하지 않는다.
    • System.out.prinln 대신에 println
    • 세미콜론(;)은 생략할수 있다. 나는 왜 버릇처럼 붙히고..

    코틀린 함수 정의

    fun max(a: Int, b: Int): Int{        // 파라미터와, 리턴타입
        return if(a < 9) a else b        // 함수 본문으로 (a>b) ? a : b 삼항연산자와 비슷하게 사용된다.
    }

    "책을 읽다 보면 if는 값을 만들어내지 못하는 문장이 아니고 결과를 만드는 식(expression)이다"라는 내용과 함께 아래처럼 설명한다.

    문(statement)과 식(expression)의 구문
    식은 값을 만들어 내며 다른 식의 하위 요소로 계산에 참여할 수 있는 반면 문은 자신을 둘러싸고 있는 가장 안쪽 블록의 최상위 요소로 존재하며 아무런 값을 만들어내지 않는다. 자바에서는
    모든 제어 구조가 무인 반면 코틀린에서는 루프를 제외한 대부분의 제어 구조가 식이다.

     

     

    중괄호로 둘러싸인 함수를 블록이 본문인 함수, 등호화 식으로 이뤄진 함수를 식이 본문인 함수라고 부른다.

    fun max(a: Int, b:Int) = if(a>b) a else b // 식이 본문인 함수 예제

    오잉? 그런데 리턴 타입인  :Int 이 사라졌다.

    코틀린에서는 반환 타입을 생략할 수 있다.

     

     

    식이 본문인 함수일 경우 굳이 사용자가 반환 타입을 적지 않아도 컴파일러가 함수 본문 식을 분석해 식의 결과 타입을 함수 반환 타입으로 정해주며 이것을 타입 추론(Type inference)라고 부른다. 크~

     

     

    변수

    - var (value) : 변경할 수 없는 참조를 저장하는 변수 단, 변경할 수 없는 변수라도 그 객체의 내부 값은 변경될 수 있다.!!

    - var (variable) : 변경 가능한 참조. 아무리 변경 가능한 변수라도 변수의 타입은 변경할 수 없다.

    // val 참조값의 변경 예제
    fun main(args: Array<String>) {
        val numbers = arrayListOf("first", "second");
        println(numbers);	// >> [first, second]
    
        numbers.add("third");
        println(numbers); // [first, second, third]
    }

     

    문자열 템플릿

    $을 붙여 스트링 처리에서 바로 변수를 사용할 수 있다. 한 가지 주의할 점은 $변수 뒤 바로 영어, 한글을 붙이면 unsesolved reference 오류가 발생하는데 이문제를 해결하기 위해 "${name}님 안녕하세요"처럼 {}을 붙이는 습관을 들이는 게 좋을 것 같다.

    val name = "kim"
    println("$name안녕하세요.");	// unresolved reference 오류발생
    println("${name}안녕하세요.");​

     

    클래스, 프로퍼티

    클래스

    코드 없이 데이터만 저장하는 클래스를 "값 객체(value object)"라 부르는데 코틀린을 이용하면 자바 코드를 매우 간단하게 변경할 수 있다.

    // 자바코드
    public class Person{
    	private final String name;
        
        public Person(String name){
        	this.name = name;
        }
        
        public String getName(){
        	return name;
        }
    }
    
    // 코틀린
    class Person(name:String);

     

    프로퍼티

    객체지향 언어를 사용하면서 클래스를 사용하는 목적 중 하나로 "캡슐화"를 생각할 수 있다. 자바에서도 접근제어자와, 필드를 이용해 정의하는데 보통 외부에서 접근할 수 없도록 private 필드를 생성하고 getter, setter을 이용하여 데이터를 저장, 호출해서 사용한다.

     

    코틀린에서는 "접근제어자 + 필드"를 묶어 프로퍼티(property)라고 부른다. 또한 코틀린은 값을 저장하기 위한 비공개 필드와 그 필드에 값을 저장하기 위한 세터, 필드의 값을 릭기 위한 게터로 워진 간단한 디폴트 접근자 구현을 제공한다.

     

    class Person(
    	val name: String, 	// 읽기 전용 프로퍼티 setter는 없고 getter만 제공한다.
    	var ismarried: Boolean  // 읽기, 쓰기 프로퍼티 setter, getter모두 제공한다.
    )

     

    # 자바와 비교한 getter, setter

    // 자바
    Person person = new Person("kim", true);
    System.out.println(person.isMarried());
    
    // 코틀린
    var person = Person("kim", true);
    println(person.isMarried);
    println(person);
    
    person.isMarried = false;
    println(person.isMarried);
    

     

    # 그렇다면 사용자가 정의하는 getter는 어떻게 사용할 수 있을까?

    fun main(args: Array<String>) {
        var pserson = Person("kim", "justin");
        println(pserson.fullName);
    }
    
    class Person(var firstName: String, var secondName: String) {
        val fullName: String
            // 프로퍼티 게터 선언
            get() {
                return "${firstName} ${secondName}";
            }
    }
    
    // 블록 본문을 더간단하게 줄일수 있다.
    class Person(var firstName: String, var secondName: String) {
        val fullName: String
            // 프로퍼티 게터 선언
            get() = "${firstName} ${secondName}"
    }

     

    enum과 when

    enum은 스마트 캐스 트을 이용 해 자바보다 편리하게 사용할 수 있고, when은 자바의 switch과 대치되며 더 강력하게 사용할 수 있다.

    enumn부터 알아봅시다.

     

    Enum

    enum에서도 일반적인 클래스와 마찬가지로 생성자, 프로퍼티를 선언한다. 각 enum상수를 정의할 때는 그 상수에 해당하는 프로퍼티 값을 지정해야 한다. 또한 enum클래스 안에서 메서드를 정의하기 위해 반드시 enum 원소의 마지막에 ;을 붙여서 구분을 해야 한다. 코틀린에서 유일하게 ;을 강제로 사용하는 곳이다.

    fun main(args: Array<String>) {
        println(Color.RED);
    
        println(ColorInfo.BLACK.str());
    }
    
    enum class Color {
        RED,
        ORANGE,
        YELLO
    }
    
    enum class ColorInfo(val r: Int, val g: Int, val b: Int) {    // 상수의 프로퍼티를 정의한다.
        BLACK(0, 0, 0),
        WHITE(255, 255, 255);
    
        fun str() = "${r}${g}${b}"
    }

     

    #when, enum의 조합 예제

    fun main(args: Array<String>) {
        println(getColorName(Color.RED));
    }
    
    fun getColorName(color: Color) = when (color) {
        Color.RED -> "레드"
        Color.ORANGE -> "오렌지"
        Color.YELLO -> "엘로우"
        else -> throw Exception("error")
    }
    
    enum class Color {
        RED,
        ORANGE,
        YELLO
    }
    

     

     

    is을 이용한 변수 타입 검사

    코틀린에서는 is을 이용해서 변수 타입을 검사할 수 있고 이는 instanceof와 비슷하다.

    is을 이용해 타입 체크를 하게 되면 자바에서 매우(?) 불편하던 캐스팅 작업들이 필요 없다. 코틀린에 자동으로 하기 때문이다.

    단,  그 값이 바뀔 수 없는 경우에만 작동한다. 이게 무슨 말이냐면 앞에서 언급한 var(variable) 변경 가능 변수는 사용할 수 없다.

    변경할 수 없는 val이어야 하며 커스텀 접근자를 사용한 것이어도 안된다. 커스텀 접근자를 사용하는 경우에는 해당 프로퍼티에 대한 접근이 항상 같은 값을 내놓는다고 확신할 수 없기 때문이다.

     

    fun main(args: Array<String>) {
        // If을 이용한방법
        println(check(Student("myStudent")))
        println(check(Teacher("myTeacher")))
    
        // when을 이용한방법
        println(checkWithWhen(Student("myStudent")))
        println(checkWithWhen(Teacher("myTeacher")))
    
    }
    
    fun check(someone: Person): String {
        if (someone is Student)
            return someone.studentName
    
        if (someone is Teacher)
            return someone.teacherName
        else
            throw Exception("error")
    }
    
    fun checkWithWhen(someone: Person) = when (someone) {
        is Student -> someone.studentName
        is Teacher -> {
            println("블럭의 마지막 값이 리턴되요.")
            someone.teacherName
        }
        else -> throw Exception("error")
    
    }
    
    class Student(val studentName: String) : Person
    class Teacher(val teacherName: String) : Person
    
    interface Person
    

     

    when, if 두 가지 방법을 사용했으며 두가지 방법 모두 블록의 마지막 라인이 return의 값으로 사용된다.

    "블록의 마지막 식이 블록의 결과라는 규칙은 블록이 값을 만들어내야 하는 경우 항상 성립니다."

     

     

    for, while

    // 변경할수 없는 변수지만 참조하고 있는 그값의 내용은 변경될 수 있다.
    val maps = TreeMap<Int, Int>();
    
    for (number in 1..10) {
    	maps[number] = number;
    }
    
    for (number in maps) {
    	println(number);
    }
    
    
    // index, value 형태의 loop
    val letters = arrayListOf("a", "b", "c");
    for ((index, value) in letters.withIndex()) {
    	println("${index} : ${value}")
    }

     

     

    다음장에선 함수 정의와 호출에 대해 알아봅시다.!

    'Kotlin' 카테고리의 다른 글

    Kotlin Clock mockito  (1) 2021.11.10
    Kotlin 기본 문법  (0) 2019.08.03
    코틀린 프로젝트 생성 및 실행  (0) 2019.03.20
    코틀린 소개  (1) 2019.03.17

    댓글

Designed by Tistory.