클래스
클래스는 다음 세 가지 주요 부분으로 구성됩니다.
- 속성. 클래스 객체의 속성을 지정하는 변수입니다.
- 메서드. 클래스의 동작과 작업이 포함된 함수입니다.
- 생성자. 클래스가 정의된 프로그램 전체에서 클래스의 인스턴스를 만드는 특수 멤버 함수입니다.
객체 인스턴스화
class SmartDevice {
// empty body
}
fun main() {
val smartTvDevice = SmartDevice() // 객체로 인스턴스화 함
}
클래스에서 메서드 정의/호출
class SmartDevice {
fun turnOn(){
println("Smart device is turned on.")
turnOff()
}
fun turnOff(){
println("Smart device is turned off.")
}
}
객체에서 메서드 호출
fun main() {
val smartTvDevice = SmartDevice()
smartTvDevice.turnOn()
smartTvDevice.turnOff()
}
// 결과
Smart device is turned on.
Smart device is turned off.
Smart device is turned off.
속성의 getter/setter 함수
속성은 변수보다 더 많은 작업을 할 수 있습니다. 예를 들어 스마트 TV를 나타내는 클래스 구조를 만든다고 가정하겠습니다. 흔히 실행하는 작업 중 하나는 볼륨을 높이거나 줄이는 것입니다. 프로그래밍에서 이 작업을 표현하려면 speakerVolume이라는 속성을 만들면 됩니다. 이 속성은 TV 스피커에 설정된 현재 볼륨 수준을 포함하지만, 볼륨 값에는 범위가 있습니다. 설정할 수 있는 최소 볼륨은 0이고 최대 볼륨은 100입니다. speakerVolume 속성이 100을 초과하거나 0 미만으로 떨어지지 않도록 하려면 setter 함수를 작성하면 됩니다. 속성 값을 업데이트할 때 값이 0~100 범위에 있는지 확인해야 합니다. 다른 예로, 이름이 항상 대문자여야 한다는 요구사항이 있다고 가정하겠습니다. name 속성을 대문자로 변환하는 getter 함수를 구현할 수 있습니다.

var speakerVolume = 2
set(value) {
field = value
}
경고: 값을 가져오거나 설정하는 속성 이름을 사용하지 마세요. 예를 들어 set() 함수에서 speakerVolume 속성 자체에 value 매개변수를 할당하려고 하면 Kotlin 런타임이 speakerVolume 속성의 값을 업데이트하려고 시도하며 이에 따라 setter 함수의 반복적 호출이 트리거되므로 코드의 무한 루프가 발생합니다.
// 무한 루프에 빠지는 코드 예시
var speakerVolume = 2
set(value) {
speakerVolume = value
}
생성자
Kotlin의 생성자에는 두 가지 기본 유형이 있습니다.
- 기본 생성자. 클래스에는 클래스 헤더의 일부로 정의된 기본 생성자가 하나만 있을 수 있습니다. 기본 생성자는 기본 또는 매개변수화된 생성자일 수 있습니다. 기본 생성자에는 본문이 없습니다. 즉, 코드를 포함할 수 없습니다.
- 보조 생성자. 한 클래스에 여러 보조 생성자가 있을 수 있습니다. 매개변수를 포함하거나 포함하지 않고 보조 생성자를 정의할 수 있습니다. 보조 생성자는 클래스를 초기화할 수 있으며 초기화 로직을 포함할 수 있는 본문을 가집니다. 클래스에 기본 생성자가 있는 경우 각 보조 생성자는 기본 생성자를 초기화해야 합니다.
기본 생성자
기본 생성자는 매개변수가 없는 생성자입니다. 다음 코드 스니펫과 같이 기본 생성자를 정의할 수 있습니다.
class SmartDevice constructor() {
...
}
Kotlin은 간결한 것을 목표로 하므로 주석이나 공개 상태 수정자가 없는 경우 constructor 키워드를 삭제할 수 있습니다. 이 생성자에 관해 곧 알아봅니다. 다음 코드 스니펫과 같이 생성자에 매개변수가 없는 경우 괄호를 삭제할 수도 있습니다.
class SmartDevice {
...
}
Kotlin 컴파일러는 기본 생성자를 자동으로 생성합니다. 자동 생성된 기본 생성자는 컴파일러가 백그라운드에서 추가하므로 코드에 표시되지 않습니다.
매개변수화된 생성자
매개변수화된 생성자를 사용하여 속성을 초기화합니다.
class SmartDevice(val name: String, val category: String) {
var deviceStatus = "online"
fun turnOn(){
println("Smart device is turned on.")
}
fun turnOff(){
println("Smart device is turned off.")
}
}
참고: 클래스에 기본 생성자가 없고 인수 없이 객체를 인스턴스화하려고 하면 컴파일러에서 오류가 보고됩니다.
보조 생성자
보조 생성자는 클래스의 본문에 포함되고 이 생성자의 문법은 세 부분으로 구성됩니다.
- 보조 생성자 선언. 보조 생성자 정의는 constructor 키워드로 시작하고 그 뒤에 괄호가 나옵니다. 해당하는 경우 괄호에는 보조 생성자에 필요한 매개변수가 포함됩니다.
- 기본 생성자 초기화. 초기화는 콜론으로 시작하고 그 뒤에 this 키워드와 괄호 쌍이 나옵니다. 해당하는 경우 괄호에는 기본 생성자에 필요한 매개변수가 포함됩니다.
- 보조 생성자 본문. 기본 생성자 초기화 뒤에 중괄호 쌍이 나오며 이 중괄호에는 보조 생성자의 본문이 포함됩니다.

예를 들어 스마트 기기 제공업체에서 개발한 API를 통합하려고 하지만 이 API가 초기 기기 상태를 나타내는 Int 유형의 상태 코드를 반환합니다. API는 기기가 오프라인인 경우 0 값을, 기기가 온라인인 경우 1 값을 반환합니다. 다른 정수 값이면 상태는 알 수 없음으로 간주됩니다. 다음 코드 스니펫에서 볼 수 있듯이 SmartDevice 클래스에 statusCode 매개변수를 문자열 표현으로 변환하는 보조 생성자를 만들 수 있습니다.
class SmartDevice(val name: String, val category: String) {
var deviceStatus = "online"
constructor(name: String, category: String, statusCode: Int) : this(name, category) {
deviceStatus = when (statusCode) {
0 -> "offline"
1 -> "online"
else -> "unknown"
}
}
...
}
클래스 간 관계 구현

1. SmartDevice 슈퍼클래스에서 open 키워드를 class 키워드 앞에 추가합니다.
open class SmartDevice(val name: String, val category: String) {
...
}
2. SmartDevice 슈퍼클래스를 확장하는 SmartTvDevice 서브클래스를 만듭니다.
class SmartTvDevice(deviceName: String, deviceCategory: String) :
SmartDevice(name = deviceName, category = deviceCategory) {
}
3. SmartTvDevice 서브클래스 본문에서 getter 함수와 setter 함수에 관해 배울 때 만든 speakerVolume 속성을 추가합니다.
class SmartTvDevice(deviceName: String, deviceCategory: String) :
SmartDevice(name = deviceName, category = deviceCategory) {
var speakerVolume = 2
set(value) {
if (value in 0..100) {
field = value
}
}
}
4. 0..200 범위를 지정하는 setter 함수를 사용하여 1 값에 할당된 channelNumber 속성을 정의합니다.
class SmartTvDevice(deviceName: String, deviceCategory: String) :
SmartDevice(name = deviceName, category = deviceCategory) {
var speakerVolume = 2
set(value) {
if (value in 0..100) {
field = value
}
}
var channelNumber = 1
set(value) {
if (value in 0..200) {
field = value
}
}
}
5. 볼륨을 높이고 "Speaker volume increased to $speakerVolume." 문자열을 출력하는 increaseSpeakerVolume() 메서드를 정의합니다.
class SmartTvDevice(deviceName: String, deviceCategory: String) :
SmartDevice(name = deviceName, category = deviceCategory) {
var speakerVolume = 2
set(value) {
if (value in 0..100) {
field = value
}
}
var channelNumber = 1
set(value) {
if (value in 0..200) {
field = value
}
}
fun increaseSpeakerVolume() {
speakerVolume++
println("Speaker volume increased to $speakerVolume.")
}
}
6. 채널 수를 늘리고 "Channel number increased to $speakerVolume." 문자열을 출력하는 nextChannel() 메서드를 추가합니다.
class SmartTvDevice(deviceName: String, deviceCategory: String) :
SmartDevice(name = deviceName, category = deviceCategory) {
var speakerVolume = 2
set(value) {
if (value in 0..100) {
field = value
}
}
var channelNumber = 1
set(value) {
if (value in 0..200) {
field = value
}
}
fun increaseSpeakerVolume() {
speakerVolume++
println("Speaker volume increased to $speakerVolume.")
}
fun nextChannel() {
channelNumber++
println("Channel number increased to $speakerVolume.")
}
}
7. SmartTvDevice 서브클래스 다음 줄에서 SmartDevice 슈퍼클래스를 확장하는 SmartLightDevice 서브클래스를 정의합니다.
class SmartLightDevice(deviceName: String, deviceCategory: String) :
SmartDevice(name = deviceName, category = deviceCategory) {
}
8. SmartLightDevice 서브클래스 본문에서 0..100 범위를 지정하는 setter 함수를 사용하여 0 값에 할당된 brightnessLevel 속성을 정의합니다.
class SmartLightDevice(deviceName: String, deviceCategory: String) :
SmartDevice(name = deviceName, category = deviceCategory) {
var brightnessLevel = 0
set(value) {
if (value in 0..100) {
field = value
}
}
}
9. 조명의 밝기를 높이고 "Brightness increased to $brightnessLevel." 문자열을 출력하는 increaseBrightness() 메서드를 정의합니다.
class SmartLightDevice(deviceName: String, deviceCategory: String) :
SmartDevice(name = deviceName, category = deviceCategory) {
var brightnessLevel = 0
set(value) {
if (value in 0..100) {
field = value
}
}
fun increaseBrightness() {
brightnessLevel++
println("Brightness increased to $brightnessLevel.")
}
}
서브클래스에서 슈퍼 클래스 메서드 재정의
override 키워드 사용
override 키워드는 서브클래스에 정의된 메서드에 포함된 코드를 실행하도록 Kotlin 런타임에 알립니다.
class SmartTvDevice(name: String, category: String) :
SmartDevice(name = name, category = category) {
var speakerVolume = 2
set(value) {
if (value in 0..100) {
field = value
}
}
var channelNumber = 1
set(value) {
if (value in 0..200) {
field = value
}
}
override fun turnOn() {
deviceStatus = "on"
println(
"$name is turned on. Speaker volume is set to $speakerVolume and channel number is " +
"set to $channelNumber."
)
}
override fun turnOff() {
deviceStatus = "off"
println("$name turned off")
}
fun increaseSpeakerVolume() {
speakerVolume++
println("Speaker volume increased to $speakerVolume.")
}
fun nextChannel() {
channelNumber++
println("Channel number increased to $channelNumber.")
}
}
요약
- OOP에는 캡슐화, 추상화, 상속, 다형성 등 4가지 기본 원칙이 있습니다.
- 클래스는 class 키워드로 정의되며 속성과 메서드를 포함합니다.
- 속성은 맞춤 getter와 setter를 가질 수 있다는 점을 제외하면 변수와 비슷합니다.
- 생성자는 클래스의 객체를 인스턴스화하는 방법을 지정합니다.
- 기본 생성자를 정의할 때 constructor 키워드를 생략할 수 있습니다.
- 상속을 통해 더 쉽게 코드를 재사용할 수 있습니다.
- IS-A 관계는 상속을 의미합니다.
- HAS-A 관계는 컴포지션을 의미합니다.
- 공개 상태 수정자는 캡슐화를 달성하는 데 중요한 역할을 합니다.
- Kotlin은 public, private, protected, internal 등 4가지 공개 상태 수정자를 제공합니다.
- 속성 위임을 사용하면 여러 클래스에서 getter 및 setter 코드를 재사용할 수 있습니다.