メインコンテンツにスキップ

🏗️ 클래스

📖 클래스란?

**클래스(Class)**는 객체를 만드는 설계도입니다. 데이터(프로퍼티)와 동작(메서드)을 하나로 묶어 관리합니다.

💡 기본 클래스

간단한 클래스

class Person {
var name: String = ""
var age: Int = 0

fun introduce() {
println("안녕하세요, ${name}입니다. ${age}살입니다.")
}
}

fun main() {
val person = Person()
person.name = "홍길동"
person.age = 25
person.introduce()
// 안녕하세요, 홍길동입니다. 25살입니다.
}

생성자

class Person(val name: String, val age: Int) {
fun introduce() {
println("안녕하세요, ${name}입니다. ${age}살입니다.")
}
}

fun main() {
val person = Person("홍길동", 25)
person.introduce()
}

🎯 생성자

주 생성자

// 주 생성자 (Primary Constructor)
class Person(val name: String, val age: Int)

fun main() {
val person = Person("홍길동", 25)
println("이름: ${person.name}")
println("나이: ${person.age}")
}

초기화 블록

class Person(val name: String, val age: Int) {
init {
println("Person 객체 생성: $name, $age")
}

init {
// 여러 개 가능
println("초기화 완료!")
}
}

fun main() {
val person = Person("홍길동", 25)
// Person 객체 생성: 홍길동, 25
// 초기화 완료!
}

보조 생성자

class Person(val name: String, val age: Int) {
var email: String = ""

// 보조 생성자
constructor(name: String, age: Int, email: String) : this(name, age) {
this.email = email
}
}

fun main() {
val person1 = Person("홍길동", 25)
val person2 = Person("김철수", 30, "kim@example.com")

println(person2.email) // kim@example.com
}

기본값

class Person(
val name: String,
val age: Int,
val email: String = "없음" // 기본값
) {
fun info() {
println("이름: $name, 나이: $age, 이메일: $email")
}
}

fun main() {
val person1 = Person("홍길동", 25)
val person2 = Person("김철수", 30, "kim@example.com")

person1.info() // 이메일: 없음
person2.info() // 이메일: kim@example.com
}

🔧 프로퍼티

getter와 setter

class Person(private var _age: Int) {
var age: Int
get() = _age
set(value) {
if (value >= 0) {
_age = value
}
}
}

fun main() {
val person = Person(25)
println(person.age) // 25

person.age = 30
println(person.age) // 30

person.age = -5 // 무시됨
println(person.age) // 30
}

계산 프로퍼티

class Rectangle(val width: Int, val height: Int) {
val area: Int
get() = width * height

val perimeter: Int
get() = 2 * (width + height)
}

fun main() {
val rect = Rectangle(10, 5)
println("면적: ${rect.area}") // 50
println("둘레: ${rect.perimeter}") // 30
}

🎨 메서드

기본 메서드

class Calculator {
fun add(a: Int, b: Int): Int {
return a + b
}

fun subtract(a: Int, b: Int): Int = a - b // 단일 표현식
}

fun main() {
val calc = Calculator()
println(calc.add(10, 5)) // 15
println(calc.subtract(10, 5)) // 5
}

메서드 오버로딩

class Printer {
fun print(text: String) {
println("문자열: $text")
}

fun print(number: Int) {
println("정수: $number")
}

fun print(number: Double) {
println("실수: $number")
}
}

fun main() {
val printer = Printer()
printer.print("Hello") // 문자열: Hello
printer.print(42) // 정수: 42
printer.print(3.14) // 실수: 3.14
}

🎯 실전 예제

은행 계좌

class BankAccount(val accountNumber: String, private var balance: Int = 0) {
fun deposit(amount: Int) {
if (amount > 0) {
balance += amount
println("${amount}원 입금. 잔액: ${balance}원")
}
}

fun withdraw(amount: Int): Boolean {
return if (amount > 0 && balance >= amount) {
balance -= amount
println("${amount}원 출금. 잔액: ${balance}원")
true
} else {
println("잔액 부족!")
false
}
}

fun getBalance(): Int = balance
}

fun main() {
val account = BankAccount("123-456", 10000)

account.deposit(5000) // 15000원
account.withdraw(3000) // 12000원
account.withdraw(20000) // 잔액 부족!

println("현재 잔액: ${account.getBalance()}원")
}

도서 관리

class Book(
val title: String,
val author: String,
val year: Int
) {
var isBorrowed: Boolean = false
private set

fun borrow(): Boolean {
return if (!isBorrowed) {
isBorrowed = true
println("'${title}' 대출 완료")
true
} else {
println("'${title}'는 이미 대출 중입니다")
false
}
}

fun returnBook() {
isBorrowed = false
println("'${title}' 반납 완료")
}

fun info() {
println("제목: $title, 저자: $author, 출판년도: $year")
}
}

fun main() {
val book = Book("코틀린 완벽 가이드", "홍길동", 2024)

book.info()
book.borrow()
book.borrow() // 이미 대출 중
book.returnBook()
book.borrow() // 성공
}

학생 성적

class Student(val name: String, val id: String) {
private val scores = mutableMapOf<String, Int>()

fun addScore(subject: String, score: Int) {
scores[subject] = score
println("${name}: ${subject} ${score}점 등록")
}

fun getAverage(): Double {
return if (scores.isEmpty()) {
0.0
} else {
scores.values.average()
}
}

fun printReport() {
println("\n=== ${name}의 성적표 ===")
println("학번: $id")
for ((subject, score) in scores) {
println("$subject: ${score}점")
}
println("평균: %.2f점".format(getAverage()))
}
}

fun main() {
val student = Student("홍길동", "2024001")

student.addScore("수학", 90)
student.addScore("영어", 85)
student.addScore("과학", 95)

student.printReport()
}

🔒 가시성 변경자

class Example {
public var publicVar = 1 // 어디서나 접근
private var privateVar = 2 // 클래스 내부만
protected var protectedVar = 3 // 상속받은 클래스도
internal var internalVar = 4 // 같은 모듈 내

fun test() {
println(publicVar) // ✅
println(privateVar) // ✅
println(protectedVar) // ✅
println(internalVar) // ✅
}
}

fun main() {
val example = Example()
println(example.publicVar) // ✅
// println(example.privateVar) // ❌
}

🤔 자주 묻는 질문

Q1. val vs var 프로퍼티?

A: val은 읽기 전용, var는 변경 가능!

class Person(
val name: String, // 읽기 전용
var age: Int // 변경 가능
)

fun main() {
val person = Person("홍길동", 25)

// person.name = "김철수" // ❌ 오류!
person.age = 26 // ✅ 가능
}

Q2. 생성자 매개변수에 val/var을 꼭 써야 하나요?

A: 프로퍼티로 만들려면 필요!

// val/var 있음 - 프로퍼티로 생성
class Person1(val name: String, val age: Int)

// val/var 없음 - 생성자 매개변수만
class Person2(name: String, age: Int) {
// 접근 불가!
}

fun main() {
val p1 = Person1("홍길동", 25)
println(p1.name) // ✅

val p2 = Person2("김철수", 30)
// println(p2.name) // ❌ 오류!
}

Q3. 클래스는 언제 사용하나요?

A: 관련된 데이터와 동작을 묶을 때!

// ❌ 데이터만 있으면 data class
data class Point(val x: Int, val y: Int)

// ✅ 동작이 있으면 일반 class
class BankAccount(private var balance: Int) {
fun deposit(amount: Int) { ... }
fun withdraw(amount: Int) { ... }
}

🎬 마치며

클래스로 객체지향 프로그래밍을 시작하세요!

핵심 정리:
✅ class로 클래스 정의
✅ 생성자로 초기화
✅ 프로퍼티(val/var)와 메서드
✅ getter/setter로 캡슐화
✅ private로 정보 은닉

다음 단계: 데이터 클래스에서 간편한 데이터 보관을 알아보세요!