클래스의 사용 방법
코틀린에서 클래스는 객체를 만들기 위한 설계도라고 할 수 있습니다. 클래스는 속성(프로퍼티)와 행동(메서드)을 정의하며, 이를 기반으로 여러 개의 객체(인스턴스)를 만들 수 있습니다.
class Person {
var name: String = ""
var age: Int = 0
fun introduce() {
println("Hi, my name is $name, and I'm $age years old.")
}
}
위 예제에서, Person
이라는 클래스가 정의되었습니다. 이 클래스는 name
과 age
라는 속성(프로퍼티)를 가지고 있으며, introduce()
라는 행동(메서드)을 가집니다. 이제 이 클래스를 사용해 인스턴스를 생성할 수 있습니다.
프로퍼티(property)와 메서드(method)
- 프로퍼티: 클래스 내부에서 선언된 변수로, 객체의 상태를 나타냅니다. 코틀린에서는 프로퍼티에 대해 자동으로
getter
와setter
가 생성됩니다. - 메서드: 클래스 내부에서 선언된 함수로, 객체의 행동을 정의합니다. 메서드는 클래스가 가진 데이터를 처리하거나 특정 기능을 수행합니다.
인스턴스(instance)란?
클래스는 설계도라면, 그 설계도로 실제 사용할 수 있는 객체를 만드는 과정이 인스턴스화입니다. 이때 만들어진 객체가 인스턴스입니다.
인스턴스를 생성하면 클래스의 속성과 동작이 메모리에 올라가서 활성화됩니다.
즉, 인스턴스를 통해서만 클래스에 정의된 프로퍼티와 메서드를 사용할 수 있습니다.
클래스 초기화 (인스턴스 생성)
클래스를 초기화한다는 것은 클래스를 기반으로 새로운 인스턴스를 생성하는 과정입니다.
이를 통해 클래스의 속성과 메서드를 메모리에 올려 사용할 수 있게 합니다.
클래스를 초기화하지 않으면 해당 클래스는 단순한 설계도로 남아 있으며, 실제로 데이터를 담거나 동작을 수행할 수 없습니다.
class Person(val name: String, var age: Int) {
fun introduce() {
println("Hi, my name is $name, and I'm $age years old.")
}
}
val person1 = Person("Alice", 25) // 인스턴스 생성
person1.introduce() // Hi, my name is Alice, and I'm 25 years old.
이 예시에서 Person
클래스는 사람을 정의하는 설계도이고, person1
이라는 인스턴스가 만들어지면서 그 설계도에 맞는 실제 데이터를 가지고 동작할 수 있게 됩니다. Person
클래스를 초기화하지 않으면 name
과 age
라는 정보를 사용할 수 없습니다.
컴패니언 객체 (인스턴스 없이 클래스 사용)
인스턴스를 만들지 않고도 클래스를 사용할 수 있는 방법이 있습니다. 그것이 바로 컴패니언 객체(Companion Object)입니다.
컴패니언 객체는 클래스 자체에 속하는 메서드나 프로퍼티를 정의할 수 있게 해줍니다.
컴패니언 객체를 만들려면 companion object
키워드를 사용해야 합니다.
컴페니언 객체를 만들면 인스턴스를 생성하지 않고 클래스 이름을 통해 바로 호출할 수 있습니다.
class Person(val name: String, var age: Int) {
companion object {
fun createDefaultPerson(): Person {
return Person("Unknown", 0)
}
}
}
val defaultPerson = Person.createDefaultPerson() // 인스턴스 없이 메서드 호출
println(defaultPerson.name) // Unknown
createDefaultPerson
메서드는 인스턴스 없이 Person
클래스 이름을 통해 바로 호출됩니다.
컴패니언 객체는 주로 공통된 기능을 제공할 때 유용하게 사용됩니다.
언제 컴패니언 객체를 사용하는가?
컴패니언 객체는 인스턴스가 필요 없는 경우에 사용합니다. 예를 들어, 클래스 전체에 관련된 공통된 작업이나 유틸리티 함수를 정의할 때 적합합니다. 하지만 개별 인스턴스마다 다른 데이터를 처리해야 하는 경우에는 인스턴스화가 필수적입니다.
상속 (Inheritance)
클래스는 다른 클래스를 상속받을 수 있습니다. 상속은 기존 클래스의 기능을 그대로 물려받고, 그 위에 새로운 기능을 추가하거나 기존 기능을 덮어쓸 수 있는 기능입니다.
부모 클래스의 메서드를 수정하거나 재정의하려면 open
과 override
키워드를 사용해야 합니다.
open
: 부모 클래스에서 자식 클래스가 메서드를 재정의할 수 있도록 허용하는 키워드.override
: 자식 클래스에서 부모 클래스의 메서드를 재정의할 때 사용.
상속받은 클래스는 하위 클래스라고 하며, 상속해주는 클래스는 상위 클래스라고 부릅니다.
예시:
// 상위 클래스
open class Animal(val name: String) { // 상속을 허용하려면 클래스에 open 키워드를 붙여야 함
fun eat() {
println("$name is eating.")
}
open fun sound() {
println("$name is making a sound.")
}
}
// 하위 클래스
class Dog(name: String) : Animal(name) {
override fun sound() { // 부모 클래스의 메서드를 재정의 (override)
println("$name is barking.")
}
}
val myDog = Dog("Buddy")
myDog.eat() // Buddy is eating.
myDog.sound() // Buddy is barking.
Animal
클래스는 상위 클래스입니다. 이 클래스는eat()
과sound()
메서드를 정의하고 있습니다.Dog
클래스는Animal
클래스를 상속받고 있으며,sound()
메서드를 재정의(override)하여 강아지의 소리를 출력하도록 변경했습니다.
상속을 통해 상위 클래스의 기능을 물려받으면서, 하위 클래스는 자신만의 메서드를 추가할 수 있습니다.
class Dog(name: String) : Animal(name) {
override fun sound() {
println("$name is barking.")
}
fun fetch() {
println("$name is fetching the ball.")
}
}
val myDog = Dog("Buddy")
myDog.eat() // Buddy is eating.
myDog.sound() // Buddy is barking.
myDog.fetch() // Buddy is fetching the ball.
위 예제에서 Dog
클래스는 fetch()
라는 새로운 메서드를 추가했습니다.
이 메서드는 Animal
클래스에는 없는 메서드로, Dog
클래스의 인스턴스에서만 사용할 수 있습니다.