Kotlin - Abstract class, interface

하동혁 ·2023년 4월 5일
0

Kotlin

목록 보기
7/10
post-thumbnail

Abstract class

  • 상속받을 클래스에서 구현해야 할 프로퍼티 및 메서드를 기술한 클래스
  • abstract 키워드와 함꼐 선언하며, 추상클래스는 객체 생성이 안됨
  • 추상적인 것을 나타내기 때문에 하위 파생 클래스에서 구체적으로 구현
  • 상속을 주기 위해서는 open 키워드를 선언해야 하는데 abstract class는 open이 기본 적용됨
  • 추상 클래스는 일반 메서드도 구현이 가능함
abstract class Shape(val name: String) {
    // 추상 메서드
    abstract fun getArea(): Double
    
    // 일반 메서드
    fun printName() {
        println("도형 이름: $name")
    }
}

class Square(name: String, val side: Double) : Shape(name) {
    // 추상 메서드 구현
    override fun getArea(): Double {
        return side * side
    }
}

class Circle(name: String, val radius: Double) : Shape(name) {
    // 추상 메서드 구현
    override fun getArea(): Double {
        return Math.PI * radius * radius
    }
}

fun main() {
    val square = Square("정사각형", 5.0)
    square.printName()
    println("넓이: ${square.getArea()}")

    val circle = Circle("원", 2.0)
    circle.printName()
    println("넓이: ${circle.getArea()}")
}

[출력 결과]
도형 이름: 정사각형
넓이: 25.0
도형 이름: 원
넓이: 12.566370614359172





interface

  • 자바와 동일하게 구현부가 없는 method + default method의 집합 (default 키워드는 필요 없음)
  • 상속을 주기위해 만들어진 클래스로 별도의 open 키워드는 필요하지 않다.
  • 인터페이스 내부 메서드를 구현할 때에는 fun 키워드 앞에 override 키워드를 붙여준다.
  • 상속받은 interface의 메서드를 모두 구현해야 한다. (default 메서드는 구현하지 않아도 된다.)
interface Vehicle {
    fun start()
    fun stop()
    
    // 인터페이스 내부에서 메서드 구현(default 메서드)
    fun horn() {
        println("Beep beep!")
    }
}

class Car : Vehicle {
    override fun start() {
        println("Car started.")
    }
    
    override fun stop() {
        println("Car stopped.")
    }
}

fun main() {
    val car = Car()
    car.start()
    car.horn() // 인터페이스에서 구현한 디폴트 메서드 호출
    car.stop()
}

[출력 결과]
Car started.
Beep beep!
Car stopped.



만약, 클래스가 여러 개의 부모 클래스를 가지고 있고, 부모 클래스들 중에서 같은 이름의 메서드가 있는 경우, super 키워드로 부모 클래스의 메서드를 호출하면 어떤 클래스의 메서드를 호출해야 할 지 모호해집니다.

이런 경우에는 super<클래스명>.메서드명() 형태로 호출하면 특정 부모 클래스의 메서드를 호출할 수 있습니다.

다음은 "super<클래스명>.메서드명()"를 사용하는 예제 코드입니다

open class A {
    open fun foo() {
        println("A's foo")
    }
}

interface B {
    fun foo() {
        println("B's foo")
    }
}

class C : A(), B {
    override fun foo() {
        super<A>.foo() // A 클래스의 foo() 호출
        super<B>.foo() // B 인터페이스의 foo() 호출
    }
}

fun main() {
    val obj = C()
    obj.foo()
}

[출력 결과]
A's foo
B's foo


0개의 댓글