본문 바로가기
Programming Language/Kotlin

[Kotlin] 인터페이스 깊게 이해하기

by ggyongi 2024. 9. 7.
반응형

실제 자주 사용되는 패턴을 통해 여러 usecase를 익혀보자.

import java.time.Instant

// Task 인터페이스
interface Task {
    val taskId: String
    val taskName: String
    val createdAt: Instant
    val dueAt: Instant
    val assignees: List<String>

    fun startTask()

    // 서브인터페이스: Task의 가변 기능 추가
    interface Mutable {
        fun updateTaskDetails(newName: String, newDueAt: Instant)
    }

    // 서브인터페이스: Task를 상속하며 기능을 제한
    interface ReadOnly : Task {
        override fun startTask() {
            throw UnsupportedOperationException("This task is read-only.")
        }
    }

    // 경량화된 데이터 클래스
    data class SimpleTask(
        override val taskId: String,
        override val taskName: String,
        override val createdAt: Instant,
        override val dueAt: Instant
    ) : ReadOnly { // ReadOnly 인터페이스 구현
        override val assignees: List<String> = emptyList() // 경량화된 상태로 빈 리스트
    }

    // 공통적인 기능을 포함하는 추상 클래스
    abstract class BaseTask(
        createdAt: Instant,
        dueAt: Instant
    ) : Task {
        private var _createdAt: Instant = createdAt
        override val createdAt: Instant
            get() = _createdAt

        private var _dueAt: Instant = dueAt
        override val dueAt: Instant
            get() = _dueAt
    }
}

구조 설명

  • Task 인터페이스: 작업 관리 시스템의 기본 인터페이스로, 작업의 ID, 이름, 생성 시간, 마감 시간, 담당자 목록을 정의합니다. startTask() 메서드를 통해 작업을 시작할 수 있습니다.
  • 서브인터페이스:
    • Mutable: 작업의 세부 정보를 수정할 수 있는 기능을 추가하는 서브인터페이스입니다. updateTaskDetails() 메서드를 통해 작업 이름과 마감 시간을 업데이트할 수 있습니다.  -> 기능 추가 역할!!
    • ReadOnly: 작업이 읽기 전용으로 동작하게 하는 서브인터페이스입니다. startTask() 호출 시 예외를 던져 작업 시작을 제한합니다. -> 기능 제한 역할!!
  • 경량화된 데이터 클래스 (SimpleTask):
    • SimpleTask는 경량화된 읽기 전용 Task로, 작업의 ID, 이름, 생성/마감 시간을 포함하지만 담당자 목록(assignees)은 빈 리스트로 설정되어 있습니다. ReadOnly 인터페이스를 구현하여 작업 시작을 제한합니다.
  • 공통 기능을 제공하는 추상 클래스 (BaseTask):
    • BaseTask는 Task 인터페이스의 공통 속성을 포함하는 추상 클래스입니다. **createdAt**과 dueAt 속성은 읽기 전용이지만, 내부적으로는 가변적(var)으로 처리됩니다. 이를 상속받아 다른 작업 클래스에서 공통 기능을 재사용할 수 있습니다.

 

 

사용예시1: MutableTask 정의

import java.time.Instant

// MutableTask 클래스: Task.Mutable을 구현하여 작업 세부 정보 수정 가능
class MutableTask(
    override val taskId: String,
    override var taskName: String,  // var로 선언하여 수정 가능
    createdAt: Instant,
    dueAt: Instant,
    override var assignees: List<String>  // var로 선언하여 수정 가능
) : Task.BaseTask(createdAt, dueAt), Task.Mutable {

    // Task.Mutable 인터페이스의 메서드 구현: 작업 세부 정보 수정
    override fun updateTaskDetails(newName: String, newDueAt: Instant) {
        this.taskName = newName
        this._dueAt = newDueAt  // BaseTask의 _dueAt 속성에 접근하여 수정
        println("Task details updated: New name = $newName, New due date = $newDueAt")
    }

    // Task 인터페이스의 startTask 메서드 구현
    override fun startTask() {
        println("Task '$taskName' has started.")
    }
}

fun main() {
    // MutableTask 인스턴스 생성
    val mutableTask = MutableTask(
        taskId = "T-2001",
        taskName = "Write API documentation",
        createdAt = Instant.now(),
        dueAt = Instant.now().plusSeconds(86400),  // 1일 후 마감
        assignees = listOf("Alice", "Bob")
    )

    // Task 정보 출력
    println("Task ID: ${mutableTask.taskId}")
    println("Task Name: ${mutableTask.taskName}")
    println("Due At: ${mutableTask.dueAt}")
    println("Assignees: ${mutableTask.assignees}")

    // Task 시작
    mutableTask.startTask()

    // Task 세부 정보 수정
    mutableTask.updateTaskDetails("Update API documentation", Instant.now().plusSeconds(172800)) // 2일 후 마감 변경

    // 수정된 Task 정보 출력
    println("Updated Task Name: ${mutableTask.taskName}")
    println("Updated Due At: ${mutableTask.dueAt}")
}

 

사용예시2: FullTask 클래스 정의

// FullTask 클래스: Task의 구체적인 구현
class FullTask(
    override val taskId: String,
    override val taskName: String,
    createdAt: Instant,
    dueAt: Instant,
    override val assignees: List<String>
) : Task.BaseTask(createdAt, dueAt) {
    
    // Task 인터페이스의 메서드 구현
    override fun startTask() {
        println("Task '$taskName' has started.")
    }
}

fun main() {
    val task = FullTask(
        taskId = "T-1001",
        taskName = "Develop feature X",
        createdAt = Instant.now(),
        dueAt = Instant.now().plusSeconds(604800), // 7일 후 마감
        assignees = listOf("Alice", "Bob")
    )

    // Task 시작
    task.startTask()

    // Task의 속성 출력
    println("Task ID: ${task.taskId}")
    println("Task Name: ${task.taskName}")
    println("Created At: ${task.createdAt}")
    println("Due At: ${task.dueAt}")
    println("Assignees: ${task.assignees}")
}

 

사용예시3: SimpleTask

fun main() {
    // SimpleTask 인스턴스 생성 (읽기 전용)
    val simpleTask = Task.SimpleTask(
        taskId = "T-1002",
        taskName = "Review project proposal",
        createdAt = Instant.now(),
        dueAt = Instant.now().plusSeconds(259200) // 3일 후 마감
    )

    // 읽기 전용 Task 출력
    println("Task ID: ${simpleTask.taskId}")
    println("Task Name: ${simpleTask.taskName}")
    println("Created At: ${simpleTask.createdAt}")
    println("Due At: ${simpleTask.dueAt}")
    println("Assignees: ${simpleTask.assignees}")

    // 읽기 전용 Task 시작 시도 (예외 발생)
    try {
        simpleTask.startTask()
    } catch (e: UnsupportedOperationException) {
        println(e.message) // 출력: This task is read-only.
    }
}
 

비전공자 네카라 신입 취업 노하우

시행착오 끝에 얻어낸 취업 노하우가 모두 담긴 전자책!

kmong.com

댓글