본문 바로가기

Kotlin

(Kotlin) Interface와 abstract의 차이점 분석

Kotlin으로 코딩을 하다 보니까 문득 이런 생각이 들었다

 

" interface와 abstract class는 생각해보면 다른 클래스에게 자신의 추상 메서드를 상속시켜서 자식 클래스에게 추상 메서드를 재정의하게 하는 것인 것 같은데 이 둘은 무슨 차이로 나눠 놓은 걸까"

 

이 부분이 궁금해서 직접 작성하면서 회고해보려고 한다

 

  • 공통점

1. 이 둘은 모두 추상 메서드를 받을 수 있기 때문에 자식 클래스에서 반드시 추상 메서드를 재정의 해야 하는 공통점이 있다

 

 예를 들어서

package org.example


//추상 클래스 선언
abstract class Calculator{
    //추상 함수 선언
    abstract fun result(num1:Int, num2:Int):Int
}

//인터페이스 구현으로도 위와 같은 구현을 할 수 있다
//interface Calculator2 {
//    fun result(num1: Int, num2: Int): Int
//}


//하위 클래스 들에서 Calculator 클래스 상속
class AddOperation: Calculator() {
    //추상 함수 재정의
    override fun result(num1: Int,  num2: Int):Int {
        return num1 + num2
    }

}

// ... 이하 생략

 

위와 같이 abstract 함수만 정의가 되어 있을 경우에는 interface를 써도 기능적인 동작은 정상 동작을 하는 것을 확인할 수 있다

 

하지만 이 둘은 위의 관점에서 봤을 때는 비슷 할 수도 있지만 엄밀히 다르다는 차이점이 있다 어떤 차이점이 있을까

 

1. 자식 클래스는 여러개의 interface를 상속을 받을 수 있지만 abstract 클래스는 여러개 상속 받을 수 없다

//추상 클래스 선언
abstract class Calculator{
    //추상 함수 선언
    abstract fun result(num1:Int, num2:Int):Int
}

//다른 추상 클래스 선언
abstract class Calculator2{
    //추상 함수 선언
    abstract fun result2(num1:Int, num2:Int):Int
}


//하위 클래스 에서 2개 이상의 추상클래스 상속을 받을 수 없다
class AddOperation: Calculator(), Calculator2() {
    //추상 함수 재정의
    override fun result(num1: Int,  num2: Int):Int {
        return num1 + num2
    }

}


//Only one class may appear in a supertype list 컴파일 오류 발생
//상위 클래스는 하나만 받을 수 있다는 컴파일 오류



// ... 이하 생략

 

위의 사례에서 보듯이 Only one class may appear in a supertype list 오류가 발생하면서 2개 이상의 클래스를 받을 수 없게 된다

그러나 interface는 여러개를 상속 받아도 상관이 없는 것을 확인 할 수 있다

//인테페이스 선언
interface Calculator{
    fun result(num1:Int, num2:Int):Int
}

//다른 다른 인터페이스 선언
interface Calculator2{
    fun result2(num1:Int, num2:Int):Int
}


//하위 클래스 에서 2개 이상의 추상클래스 상속을 받을 수 없다
class AddOperation: Calculator, Calculator2 {
    //추상 함수 재정의
    override fun result(num1: Int,  num2: Int):Int {
        return num1 + num2
    }

    override fun result2(num1: Int,  num2: Int):Int {
        return num1 + num2
    }

}

// 컴파일 오류 없음

// ... 이하 생략

 

* Tip : interface 여러개와 abstract class 하나만 상속을 받는 부분은 가능하다

 

2. 모든 메서드가 자동으로 추상 메서드가 되는 interface와는 달리 abstract class는 추상 메서드와 일반 메서드를 선택해서 구현이 가능하다

//추상 클래스 선언
abstract class Calculator{
    //추상 함수 선언
    abstract fun result(num1:Int, num2:Int):Int
    
    fun language(){
        println("언어입니다")
    }
}

//인터페이스 선언
interface Calculator2{

    fun result2(num1:Int, num2:Int):Int
}

 

위와 같이 추상 메서드에서는 추상적인 함수를 제외한 정식적인 기능을 가진 함수를 구현할 수 있지만 interface는 추상적인 함수만 구현이 

 

가능하다는 차이점이 있다

 

  • 어떤 식으로 사용하는 것이 좋을까??
  • abstract 클래스는 공통적인 기능을 필요로 하고 추가적인 기능 로직이 다른 경우에 사용하는 것이 좋다
  • interface는 클래스의 전체적인 기본 틀을 잡을 때 사용하는 것이 좋다

오늘의 결론

- abstract 클래스와 interface는 서로 다른 구조를 가지고 있지만 비슷한 구현을 할 수 있다

- abstract 클래스는 자식 클래스가 공통적인 기능을 가지고 있고 세부 기능만 자식 클래스가 구현하면 되는 경우 사용 하는 것이 좋다

- interface는 큰 틀에서 기본 기능을 구현할 때 사용하는 것이 좋다