Uknow's Lab.
article thumbnail

 

POJO (Plain Old Java Object)

class Person {
    String name;
    int age;
    int height;
    double weight;

    public Person(String name, int age, int height, double weight) {
        this.name = name;
        this.age = age;
        this.height = height;
        this.weight = weight;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public double getWeight() {
        return weight;
    }

    public void setWeight(double weight) {
        this.weight = weight;
    }
}

 

위와 같이 데이터를 담을 목적으로 만든 클래스를 POJO (Plain Old Java Object)라고 합니다.

별 다른 기능을 하지 않는, 정말 데이터를 담기 위한 클래스인데요.

 

인텔리제이 등 요즘은 IDE가 발전하여 getter/setter와 생성자를 자동으로 생성해주지만,

아무래도 코드도 길어지고, 귀찮습니다. 결국 보일러 플레이트가 있다는 건 똑같고요.

 

 

코틀린의 자동 getter / setter

// 몸통(중괄호 { }) 가 필요하지 않을 경우 생략 가능
class Person(val name:String, var age:Int, var height:Int, var weight:Double)


fun main() {
    val person = Person("홍길동", 30, 180, 80.5)
    println(person.name) // person.getName() -> person.name 으로 접근 가능
    person.age = 30 // person.setAge(30) -> person.age = 30 으로 접근 가능
    println(person.age) // person.getAge() -> person.age로 접근 가능
}

// 출력
>>> 홍길동
30

 

하지만, 코틀린에서는 getter / setter를 자동으로 만들어줍니다.

그 길던 코드가 단 한 줄로, 생성자, getter / setter 까지 다 처리했습니다.

 

 

프로퍼티 (Property) vs 변수 (Variable)

class Person {
    val name:String = "홍길동"
    var age:Int = 20
    var height:Int = 180
    var weight:Double = 80
}

 

클래스 안에서 정의된 변수는 프로퍼티라고 부릅니다.

이는 변수이긴 하지만, getter / setter가 내장되어 있기 때문이죠.

 

class Person {
	val name: String = "홍길동"
		get() = field
		set(value) {field = value}
}

코틀린에서는 위와 같이, getter와 setter가 자동으로 내장되어 있습니다.

개발자가 커스텀 getter / setter를 필요로 하는게 아니라면,

getter / setter를 굳이 만들어 줄 필요가 없어요.

 

 

getter / setter 커스텀

class Person {
    var name: String = "홍길동"
        set(value) {
            field = "$value  (개명함)"
        }
        get() {
            field = "나는 $field 이다"
            return field
        }
}


fun main() {
    val person = Person()
    println(person.name)
    person.name = "김철수"
    println(person.name)
}


// 출력
>> 나는 홍길동 이다
나는 김철수  (개명함) 이다

 

물론, 이 처럼 getter / setter를 커스터마이징 하여 사용하는 것이 가능합니다.

 

 

데이터를 담기 위한 클래스 Data Class

data class Person(val name: String, var age:Int, var height:Int, var weight:Double)

 

코틀린에서는 이러한 데이터를 다루는데 최적화 된 데이터용 클래스인 data class를 제공합니다.

data class는 아래 기능들을 기본적으로 제공합니다.

 

 

copy()

data class Person(val name:String, var age:Int, var height:Int, var weight:Double)

fun main() {
    val person = Person("홍길동", 10, 160, 50.6)
    val person2 = person.copy()
    val person3 = person.copy(name="전우치")
}

 

객체를 복사하거나, 특정 프로퍼티만 바꿔 복사할 때, copy() 메소드를 사용할 수 있습니다.

 

 

toString()

data class Person(val name:String, var age:Int, var height:Int, var weight:Double)

fun main() {
    val person = Person("홍길동", 10, 160, 50.6)
    println(person.toString())
}

// 출력
>>> Person(name=홍길동, age=10, height=160, weight=50.6)

 

객체의 원소를 출력하는 toString() 역시 자동으로 지원합니다.

진짜 편해요.

 

 

data class Person(val name:String, var age:Int, var height:Int, var weight:Double) {
    override fun toString(): String {
        return "이름 : $name, 나이 : $age, 키 : $height,  몸무게 : $weight"
    }
}

fun main() {
    val person = Person("홍길동", 10, 160, 50.6)
    println(person.toString())
}

// 출력
>>> 이름 : 홍길동, 나이 : 10, 키 : 160,  몸무게 : 50.6

물론, toString()을 오버라이딩하여 커스텀하여 사용할 수 있습니다.

 

 

구조 분해 (Destructuring)

data class Person(val name:String, var age:Int, var height:Int, var weight:Double)

fun main() {
    val person = Person("홍길동", 10, 160, 50.6)
    val (name, age, height, weight) = person
}

 

코틀린에서는 디스트럭쳐링일 지원합니다.

객체의 구조를 분해하여, 각각의 변수에 할당하는 기능입니다.

이 역시 익숙해지면 굉장히 편한 기능 중 하나입니다.

다만, data class의 프로퍼티가 많으면, 오히려 더 귀찮을 수 있으니

때에 따라 적절히 사용해야겠지요.

 

 

데이터 클래스 비교

class Person(var name: String, var age:Int, var height:Int, var weight:Double)

fun main() {
    val p1 = Person("John", 20, 180, 70.5)
    val p2 = Person("John", 20, 180, 70.5)

    println(p1 == p2)
}

// 출력
>> false


==============================================================


data class Person(var name: String, var age:Int, var height:Int, var weight:Double)

fun main() {
    val p1 = Person("John", 20, 180, 70.5)
    val p2 = Person("John", 20, 180, 70.5)

    println(p1 == p2)
}

// 출력
>> true

 

객체는 모두 서로 다릅니다. 따라서 두 객체를 비교하면 당연히 false가 나옵니다.

 

하지만 data class는 ==를 사용해 비교 시, 객체의 프로퍼티를 비교하기 때문에,

객체의 프로퍼티가 같을 경우 true를 반환합니다.

profile

Uknow's Lab.

@유노 Uknow

인생은 Byte와 Double 사이 Char다. 아무말이나 해봤습니다.