학습
Kotlin 객체지향 프로그래밍 심화
Kotlin 객체지향 프로그래밍 심화 — 중급
객체지향 프로그래밍 심화
1. 도입 (왜 배워야 하는가)
객체지향 프로그래밍(OOP)은 소프트웨어 개발에서 매우 중요한 패러다임입니다. OOP의 핵심은 '객체'라는 개념을 통해 현실 세계를 모델링하고, 코드의 재사용성과 유지보수성을 극대화하는 것입니다. 객체지향 프로그래밍을 잘 이해하고 활용하지 못하면, 코드가 복잡해지고 오류가 발생하기 쉬우며, 팀 프로젝트에서 협업이 어려워질 수 있습니다. 또한, 코드의 가독성이 떨어져 새로운 개발자가 기존 코드를 이해하는 데 시간이 많이 소요될 수 있습니다.
2. 핵심 개념 설명
2.1. 클래스와 객체
- 클래스: 속성과 행동을 가진 객체의 청사진입니다. 예를 들어, '자동차'라는 클래스를 정의하면, 속성으로는 색상, 모델, 연식 등이 있을 수 있습니다.
- 객체: 클래스를 기반으로 생성된 실체입니다. '빨간색 현대 아반떼'는 '자동차' 클래스의 객체입니다.
- 상속: 한 클래스가 다른 클래스를 기반으로 새로운 클래스를 만드는 것입니다. 예를 들어, '차량'이라는 클래스를 만들고, 그 클래스를 상속받아 '자동차'와 '오토바이' 클래스를 만들 수 있습니다.
- 다형성: 같은 이름의 메소드가 다른 동작을 할 수 있는 능력입니다. 예를 들어, '그리다'라는 메소드는 '원' 객체에서는 원을 그리고, '사각형' 객체에서는 사각형을 그릴 수 있습니다.
2.2. 상속
2.3. 다형성
| 용어 | 설명 |
|---|---|
| 클래스 | 객체를 생성하기 위한 설계도 |
| 객체 | 클래스의 인스턴스, 메모리에 할당된 실체 |
| 상속 | 기존 클래스의 속성과 메소드를 재사용하는 방법 |
| 다형성 | 동일한 메소드가 다양한 방식으로 동작하는 성질 |
3. 기본 코드 예제
// 자동차 클래스를 정의합니다.
class Car(val color: String, val model: String) {
fun drive() {
println("운전 중입니다: $color $model")
}
}
// Car 클래스의 객체를 생성합니다.
val myCar = Car("빨간색", "현대 아반떼")
// 객체의 메소드를 호출합니다.
myCar.drive()
실행 결과:
운전 중입니다: 빨간색 현대 아반떼
class Car(val color: String, val model: String): Car라는 클래스를 정의하고, 색상과 모델이라는 두 개의 속성을 가집니다.fun drive(): 자동차가 운전 중임을 출력하는 메소드를 정의합니다.val myCar = Car("빨간색", "현대 아반떼"): Car 클래스의 객체를 생성합니다.myCar.drive(): myCar 객체의 drive() 메소드를 호출하여 운전 중임을 출력합니다.4. 실전 활용 예제
4.1. 쇼핑몰 장바구니 구현
장바구니 기능을 구현할 때, 상품의 속성과 행동을 클래스로 정의하고 이를 상속받아 다양한 상품 클래스를 만들 수 있습니다.
open class Product(val name: String, val price: Double) {
open fun display() {
println("상품명: $name, 가격: $price")
}
}
class Book(name: String, price: Double, val author: String) : Product(name, price) {
override fun display() {
println("책 제목: $name, 가격: $price, 저자: $author")
}
}
val book = Book("Kotlin 프로그래밍", 30000.0, "홍길동")
book.display()
4.2. 게임 캐릭터 클래스
게임에서 캐릭터의 다양한 능력을 다형성을 통해 구현할 수 있습니다.
open class Character(val name: String) {
open fun attack() {
println("$name이(가) 공격합니다!")
}
}
class Warrior(name: String) : Character(name) {
override fun attack() {
println("$name이(가) 검으로 공격합니다!")
}
}
class Mage(name: String) : Character(name) {
override fun attack() {
println("$name이(가) 마법으로 공격합니다!")
}
}
val warrior = Warrior("전사")
val mage = Mage("마법사")
val characters: List<Character> = listOf(warrior, mage)
characters.forEach { it.attack() }
5. 흔한 실수와 주의사항
5.1. 잘못된 상속 사용
class Dog : Animal() {
fun bark() { println("멍멍") }
}
open class Animal {
open fun sound() {}
}
class Dog : Animal() {
override fun sound() { println("멍멍") }
}
주의사항: 상속할 클래스에 open 키워드를 사용하여 상속이 가능하도록 해야 합니다.
5.2. 다형성의 오해
fun makeSound(animal: Animal) {
animal.sound() // 동작하지 않음
}
fun makeSound(animal: Animal) {
animal.sound() // 올바르게 작동
}
주의사항: 다형성을 이용할 때는 항상 부모 클래스 타입으로 매개변수를 받아야 합니다.