[Kotlin] 인터페이스(Interface) 와 추상클래스(abstract class)

곽호택·2021년 8월 22일
0

코틀린

목록 보기
3/6
post-thumbnail

! 안드 스터디에서 BaseActivity와 BaseFragment에 대해 공부하고 코드를 작성하던 중에 추상 클래스에 대한 나의 무지함에...안타까웠다 사실 interface도 뭔지 제대로 모르고 사용하곤 해서 이번 기회에 공부해서 정리해봤다😏

1. 인터페이스(Interface)

동일한 목적하에 동일한 기능을 수행하도록 강제하는 구현 부분이 없도록 만들 수 있는 클래스이다.

여기까지만 들었을 때 솔직히 무슨 말인지 잘 모르겠다! 그래서 자세한 내용은 코드 예시를 통해서 알아보도록 하자.

우리가 학생, 직장인, 취준생을 구현하고자 할때, 이들의 공통점은 사람이기 때문에 잠을 잔다는 것이다. 그러므로 Person이라는 클래스를 만들고 sleep() 함수를 만들어 이를 이 세가지 클래스에 상속시키려 한다.

아래 코드는 위에 설명한 내용과 같다.

open class Person {
    open fun sleep() {
        println("자는 중")
    }
}

class Student : Person() {
    override fun sleep() {
        println("학생 자는 중")
    }
}

class Worker : Person() {
    override fun sleep() {
        println("직장인 자는 중")
    }
}

class JobSeeker : Person(){
    override fun sleep() {
        println("취준생 자는 중")
    }
}

fun main() {
    val ar: Array<Person> = arrayOf(Student(), Worker(), JobSeeker())
    for (person in ar){
        person.sleep()
    }
}

실행시
학생 자는 중
직장인 자는 중
취준생 자는 중

여기서 의문점이 드는 것은 Person 클래스에서 구현된 sleep()함수는 사용하지 않는다.

그렇다면 Person의 구현 부분을 만들지 않고 sleep() 함수를 다른 클래스에서 사용할 수 없을까??

바로 이때 사용하는 것이 인터페이스(Interface)이다.

2. 인터페이스(Interface) 특징

  • 인터페이스는 객체를 생성할 수 없다. 그러므로 다른 클래스에서 인터페이스를 상속 받고, 그 클래스에서 인터페이스의 구현 부분을 채우고 클래스의 객체를 생성해서 사용한다.

위의 코드를 다시 예를 들자면 다음과 같다.

interface Person {
    fun sleep()
}

class Student : Person {
    override fun sleep() {
        println("학생 자는 중")
    }
}

class Worker : Person {
    override fun sleep() {
        println("직장인 자는 중")
    }
}

class JobSeeker : Person{
    override fun sleep() {
        println("취준생 자는 중")
    }
}

fun main() {
    val ar: Array<Person> = arrayOf(Student(), Worker(), JobSeeker())
    for (person in ar){
        person.sleep()
    }
}
  • 클래스를 상속받을 때와는 달리 Person 뒤에 ()가 없고, 인터페이스 sleep() 함수의 구현부가 없다.

  • 코틀린 인터페이스는 val/var과 같은 프로퍼티도 포함이 가능한데 대신 인터페이스 안에서 이들을 초기화 해줄 수 는 없다.

interface Person {
    fun sleep()
    val sleepTime : Int
    val goodSleep : Boolean
}
  • 인터페이스는 밑에서 언급할 추상 클래스와 달리 구현 부분을 가질 수 있고, 구현했을 경우 디폴트 구현으로 적용된다.

  • 인터페이스에서 메서드 및 프로퍼티를 구현하지 않을 경우 구현하는 클래스에서는 반드시 구현해야 한다!

  • 인터페이스를 선언시 다른 인터페이스를 상속 받을 수 있고, 인터페이스는 여러 개를 구현할 수 있다.

3. 추상 클래스(abstract class)

미완성 함수 혹은 실행 영역이 없는 함수.

추상 클래스는 일반 클래스와 인터페이스의 특징이 혼합되어 있다.

  • 추상 메소드와 일반 메소드 둘다 사용이 가능하다. 하지만 추상 메소드가 하나라도 있을 경우 그 클래스는 추상클래스가 되어야 한다. 프로퍼티도 마찬가지고

  • class앞에 abstract를 붙여준다. abstract class <함수명>

  • 추상 메소드는 블록{}으로 둘러싸인 구현부를 가질 수가 없다!

  • 인터페이스와 마찬가지로 객체를 생성할 수는 없지만 생성자를 가질 수 있다.

아래 코드는 위에 사용했던 Person이라는 인터페이스를 추상 클래스로 변형하여 나타냈다.

abstract class Person {
    abstract fun sleep()

    abstract val sleepTime : Int
    abstract val goodSleep : Boolean
    
    val earlySleep = true
}

class Student : Person() {
    override fun sleep() {
        println("학생 자는 중")
    }

    override val sleepTime: Int
        get() = 3
        
    override val goodSleep = true
}

클래스이기 때문에 상속받는 부분에서 Person() 괄호를 넣어주었고, 추상 프로퍼티를 사용해도 되고 일반 프로퍼티를 사용해도 된다.

  • 추상 메소드 및 추상 프로퍼티의 경우에는 반드시 상속받는 클래스에서 override 해줘야한다.

  • 특정 클래스는 반드시 하나의 추상 클래스만 상속받아야 하고, 추상 클래스가 추상 클래스를 상속받는 것은 가능하다.

이상 정리 끝!

profile
잘하고싶다

0개의 댓글