[Kotlin] Class

Hood·2025년 4월 16일

Kotlin

목록 보기
16/18
post-thumbnail

✍  코틀린과 친해지자

공부가 필요한 문법에 대해서 정리한 글입니다.


들어가기 전

OOP(Object-Oriented Programming, 객체지향 프로그래밍)는 컴퓨터 프로그램을 객체라는 단위로 구성하여, 객체의 관점에서 프로그래밍하는 방법입니다.
프로그래밍을 하다 보면 반드시 한 번쯤은 접하게 되는 개념입니다.
객체지향 프로그래밍 언어를 사용한다는 것은 결국 객체(Object)를 활용한다는 뜻입니다.
객체는 클래스에서 정의한 내용을 바탕으로 생성되며,
실제 메모리 공간에 할당되고 식별자에 의해 참조됩니다.
객체 는 변수, 데이터(자료 구조), 함수 또는 메서드를 포함할 수 있는 독립적인 단위입니다.
이번 포스트에서는 객체를 정의하는 클래스에 대해 알아보려고 합니다.


클래스

클래스(Class)를 정의하면 객체 지향 프로그래밍에서 특정 객체를 생성하기 위한
변수와 메서드를 정의하는 것 입니다.
일종의 설계도이기 때문에 비슷한 구조를 갖지만 상태가 서로 다른 많은 객체를 만들 수 있는
특징을 가지고 있습니다.


참조

주 생성자

클래스를 정의할 때 가장 기본이 되는 생성자입니다.
클래스 헤더 바로 옆에 선언되는 생성자로 주 생성자를 사용하면 클래스를 간결하고 명활하게
정의할 수 있다는 것이 특징입니다.

class User(val name: String, var age: Int) //()안에 주 생성자

fun main(){
    val user = User("DH", 24)
    println(user.name) // DH
}

초기화 블록 (init)

init 블록은 객체가 생성될 때 실행되는 코드이며 주 생성자에서 받은 값으로 무언가 추가 처리를
하고 싶을 때 많이 사용합니다.
예를 들면 User가 생성되었다면 만들어졌다고 알림이 보내졌습니다.
이때 init 블럭을 사용해 작성하면?

class User (val name : String, val age : Int){
    init {
        println("User가 생성되었습니다! 이름 : $name, 나이 : $age")
    }
}

fun main(){
    val newUser = User("DH", 24) //User가 생성되었습니다! 이름 : DH, 나이 : 24
}

부 생성자

만약 클래스 안에 생성자를 더 추가하고 싶다면 그 때 사용할 수 있는 부 생성자가 있습니다.
선언하는 방법은 constructor() 키워드를 통해 사용 가능하며 this 키워드로
주 생성자의 키를 호출하여 정의할 수 있습니다.

class Person (val name : String, val age : Int){
    init {
        println("Person이 생성되었습니다! 이름 : $name, 나이 : $age")
    }
    var email: String = "Unknown@example.com"

    constructor(name : String, age : Int, email: String) : this(name, age){
        this.email = email
    }
}

fun main(){
    val newPerson = Person("DH", 24) //User가 생성되었습니다! 이름 : DH, 나이 : 24
    println("${newPerson.name}, ${newPerson.email}") //DH, Unknown@example.com
}

this.email = email 해당 부분으로 자동적으로 setter가 생성됩니다.
여기서 알 수 있는 부분은 코틀린에서는 프로퍼티를 통해 직접 접근하는 듯 보여도
내부적으로는 getter/setter를 호출한다는 것 입니다.

이를 잘 활용해서 이름 길이에 대해 필터를 걸어보면

class User (val name : String, val age : Int){
    init {
        if(name.length > 3){
            throw IllegalArgumentException("이름은 3글자를 넘어갈 수 없습니다.")
        }
        println("User가 생성되었습니다! 이름 : $name, 나이 : $age")
    }
}

fun main(){
    val newUser = User("HDH1234", 24)
    //Exception in thread "main" java.lang.IllegalArgumentException: 이름은 3글자를 넘어갈 수 없습니다.
}

init 블록 안에 이런 식으로 throw를 통해 exception도 넘겨줄 수 있습니다.

this

this 키워드는 클래스 자기 자신을 참조한다는 뜻 입니다.
같은 이름의 변수나 속성이 있을 때 주요 사용합니다.

class Box (val width: Int){
    fun printWidth(){
        println("너비 : ${this.width}")
    }
}

fun main(){
    val box = Box(25).printWidth() //너비 : 25
}

Override

Override는 상위 클래스가 가지고 있는 메서드를 하위 클래스에서 재정의하여
사용할 수 있는 상속의 개념입니다.
예를 들면 동물이 동물소리를 내는데 동물 마다의 울음소리가 달라 상위에는 동물을 정의하고
하위에는 동물을 상속받아 울음 소리를 다시 정의하는 것과 같습니다.
여기서 코틀린은 클래스 앞에 open 키워드를 통해 상속 가능하게 만듭니다.

open class Animal {
    open fun speak() = println("동물 소리")
}

class Cat : Animal() {
    override fun speak() {
        println("야옹!")
    }
}

fun main() {
    val cat = Cat().speak() //야옹!
}

추상 클래스

추상 클래스(abstract) 도 마찬가지로 상속을 하는 개념인데 여기서는
부모는 단지 설계도를 내주면 자식이 알아서 책임지는 클래스입니다.
위의 오버라이딩은 부모 클래스의 기능을 다시 자식 클래스가
정의하는 것을 보면 자식에게 맡긴다는 차이점이 있습니다.

abstract class Animal {
    abstract fun sound()
}

class Cat : Animal() {
    override fun sound() {
        println("야옹!")
    }
}

fun main(){
    val cat = Cat() // 야옹!
}

📌 결론

클래스는 OOP에 사용되는 객체를 정의하는 데 사용됩니다.
예를 들면 모든 사물이나 개념(객체)을 만드는 틀을 만드는 개념으로 이해하면 쉽습니다.
이 안에는 init (초기화 블록), 변수 (프로퍼티), 함수 (메소드) 등이 들어옵니다.

profile
달을 향해 쏴라, 빗나가도 별이 될 테니 👊

0개의 댓글