본문 바로가기
Language/Kotlin

[Kotlin IN ACTION] - Kotlin 클래스와 프로퍼티

by Jman 2022. 7. 5.

2.2   클래스와 프로퍼티

 

2.2.1  클래스

/* 자바 */
public class Person {
	private final String name;
}


/* 코틀린 (값 객체)*/
class Person(val name : String)

 

클래스에서 코틀린의 기본 가시성은 public 이므로 이런 경우 변경자를 생략해도 된다.

 

2.2.2   프로퍼티

class Person (
    val name : String, // 읽기 전용 프로퍼티, 
                       // 코틀린은 (비공개)필드와 필드를 읽는 단순한(공개)게터를 만들어낸다.
    var isMarried : Boolean // 쓸 수 있는 프로퍼티,
                            // 코틀린은 (비공개)필드, (공개)게터, (공개)세터를 만들어낸다.
)

 

 

자바에 있는 필드, 접근자를 한데 묶어 프로퍼티(property)라고 부르며, 프로퍼티라는 개념을 활용하는 프레임워크가 많다.

  • val : 읽기 전용 프로퍼티 선언
  • var : 변경 가능한 프로퍼티 선언

 

자바와 코틀린 비교

/* 자바 */
Person person = new Person("Bob", true);

//getter
System.out.println(person.getName());
System.out.println(person.isMarried());
//setter
person.setMarried(false); 

/* 코틀린 */
val person = Person("Bob", true) // new 키워드를 사용하지 않고, 생성자를 호출

//getter
// 프로퍼티 이름을 직접 사용해도 자동으로 게터를 호출
println(person.name)  
println(person.isMarried)
//setter
person.isMarried = false
Tip.
자바에서 선언한 클래스에 대해 코틀린 문법을 사용해도 된다.

 

대부분의 프로퍼티에는 그 프로퍼티의 값을 저장하기 위한 필드가 있다.

이를 프로퍼티를 뒷받침하는 필드 (Backing field) 라고 부른다.

 

 

2.2.3  커스텀 접근자

프로퍼티의 접근자를 직접 작성하는 방법이다.

class Rectangle(val height : Int, val width : Int) {
	val isSquare : Boolean 
    	get() {  // 프로퍼티 게터 선언
        	return height == width
        }
}

직사각형이 정사각형인지를 별도의 필드에 저장할 필요가 없다.

사각형의 너비와 높이가 같은지 검사하면 정사각형 여부를 그때그때 알 수 있다.

 

 

2.2.4    코틀린 소스코드 구조 : 디렉터리와 패키지

클래스 임포트와 함수 임포트에 차이가 없으며, 모든 선언을 import 키워드로 가져올 수 있다.

최상위 함수는 그 이름을 써서 사용할 수 있다.

 

geometry/shapes/Rectangle.kt

package geometry.shapes

import java.util.Random


class Rectangle (
    val height : Int,
    val weight : Int
) {
    val isSquare : Boolean
        get() {
            return height == weight
        }
}

fun createRandomRectangle() : Rectangle {
    val random = Random()
    return Rectangle(random.nextInt(), random.nextInt())
}

geometry/example/Main.kt

package geometry.example

import geometry.shapes.createRandomRectangle

class Main {
}

fun main() {
    val r = createRandomRectangle()
    println(r.height)
    println(r.weight)
    println(r.isSquare)
}

 

코틀린에서는 여러 클래스를 한 파일에 넣을 수 있고, 파일의 이름도 마음대로 정할 수 있다.

코틀린에서는 디스크상의 어느 디렉터리에 소스코드 파일을 위치 시키든 상관없다.

따라서 원하는 대로 소스코드 구성할 수 있다.

 

 

2.3  선택 표현과 처리 : enum 과 when

when은 자바의 switch를 대치하되 훨씬 강력하며, 앞으로 더 자주 사용할 프로그래밍 요소라고 생각할 수 있다.

2.3.1   enum 클래스 정의

enum class Color {
    RED, ORANGE, YELLOW, GREEN, BLUE, INDIGO, VIOLET
}

enum 은 자바 선언보다 코틀린 선언에 더 많은 키워드를 써야하는 흔치 않은 예다.

 

enum class Color (
    val r : Int,
    val g : Int,
    val b : Int
) {
    RED(255, 0, 0),
    ORANGE(255, 165, 0),
    YELLOW(255, 255, 0),
    GREEN(0, 255, 0),
    BLUE(0, 0, 255),
    INDIGO(75, 0, 130),
    VIOLET(238, 130, 238);

    fun rgb() = (r * 256 + g) * 256 + b
}

위 코드는 enum 에 단순히 값만 열거하는 게 아닌, 프로퍼티나 메소드를 정의한 경우다.

각 enum 상수를 정의할 때는 그 상수에 해당하는 프로퍼티 값을 지정 해야한다.

또한, 세미콜론(;) 이 필수인 부분을 볼 수 있다. 

enum 클래스 안에서 메소드를 정의하는 경우 반드시 enum 상수 목록과 메소드 정의 사이에 세미콜론을 넣어야 한다.

 

2.3.2   when 으로 enum 클래스 다루기

fun getMnemonic(color: Color) =
    when (color) {
        RED -> "영수"
        BLUE -> "희철"
        ORANGE -> "상수"
        YELLOW -> "라면"
        GREEN -> "잔디"
        INDIGO -> "인디아나존수"
        VIOLET -> "보라돌이"
    }

 

when 분기 안에 여러 값 적용하기

자바와 달리 break 를 넣지 않아도 된다. 

 

2.3.3   when과 임의의 객체를 함께 사용

코틀린에서 when 은 자바의 switch 보다 훨씬 더 강력하다.

분기 조건에 상수(enum 상수나 숫자 리터럴)만 사용할 수 있는 자바 switch와 달리 코틀린 when의 분기 조건은 임의의 객체를 허용한다.

// 집합 비교를 사용하기 위해 집합(Set) 컬렉션을 사용한다.

fun mix(c1 : Color, c2 : Color) =
    when(setOf(c1, c2)) { // 인자로 받은 집합(Set) 객체를
    
    	// 여기서 있는 비교를 하고, 있을 시 그에 해당한 값을 열거한다.
        setOf(RED, YELLOW) -> ORANGE 
        setOf(BLUE, YELLOW) -> GREEN
        setOf(BLUE, VIOLET) -> INDIGO
        else -> throw Exception("Dirty color") // 매치되는 분기 조건이 없을 시, 익셉션 에러
    }