Mobile/Kotlin

[Kotlin] 추상 클래스와 인터페이스

클리엘 2020. 12. 10. 09:43
728x90

클래스라는 것을 만들어 두면 이것을 인스턴스화 하여 객체를 생성하고 객체를 통해 클래스의 기능을 이용하게 됩니다. 객체지향 언어(코틀린은 함수형언어)에서 클래스는 객체를 구체화한 것인데 이 구체화 단계가 명확하게 떨어지지 않을 때 추상 클래스를 사용하게 됩니다.

 

예를 들어 고양이라는 대상이 있으면 고양이를 클래스로 만들어 구체화 할 수 있고, 고래가 있으면 고래라는 클래스를 만들어 구체화할 수 있을 것입니다. 그런데 '동물'이라는 대상이 있으면 얘는 어떻게 클래스로 만들어 구체화할까요?

 

'동물'이라는 대상은 개인지 고양이인지, 고래인지, 두더지인지.. 암튼 특정 류의 동물에 따라 구체화할 수 있는 방법이 달라집니다. 객체 자체가 명확하지 않은 셈인데 이렇게 불분명한 상태를 나타내고자 할 때 이걸 추상 클래스(abstract)나 인터페이스(interface)로 구현하고 명확한 객체를 대상으로 클래스를 만들 때 이들로부터 상속하여 좀 더 구체화하는 것으로 클래스의 설계가 진행되는 것입니다.

 

(1) 추상 클래스

 

추상 클래스는 abstract키워드로 클래스가 작성됩니다.

abstract class Animal {
    abstract fun eat()
    abstract fun move()
}

동물이 먹는 방법과 이동하는 방법이 어떤 동물이냐에 따라 달라진다는 판단하에 추상적으로 껍데기만 구현해 놓는 것입니다.

 

하지만 간혹 추상 클래스 안에서도 어떤 내용이 구체화될 수 있는 경우도 있는데 이때는 온전한 메서드를 구현해 놓습니다.

abstract class Animal {
    abstract fun eat()
    abstract fun move()
    fun sleep() {
        Log.d("test", "동물이 잠을 잔다.")
    }
}

이제 클래스를 구현하는 단계에서 추상 클래스를 상속해 메서드를 구체화합니다. 이때 추상클래스의 메서드는 override를 통해 재정의 하는 것으로 구체화 합니다.

class Whale : Animal() {
    override fun eat() {
        Log.d("test", "고래가 먹이를 먹다.")
    }
    
    override fun move() {
        Log.d("test", "고래가 헤엄쳐 이동하다.")
    }
}

(2) 인터페이스

 

추상 클래스와 거의 비슷한 개념이지만 차이점은 인터페이스는 절대로 메서드의 구체적인 구현을 가지지 않는다는 점입니다. 추상클래스에서 예로 든 'sleep()'메서드는 추상클래스 안에서 이미 구현되어 있기 때문에 이를 상속받는 클래스에서는 다시 재정의 하지 않아도 자유롭게 해당 메서드를 호출할 수 있습니다.

var a = Whale()
a.sleep()

하지만 인터페이스는 순수히 속성이나 메서드의 이름만 가질 수 있으며 interface키워드를 사용해 다음과 같이 구현할 수 있습니다.

interface Animal {
    var name: String
    fun eat()
    fun move()
}

물론 인터페이스를 상속받는 클래스는 이를 모두 구현해야 합니다.

class Whale : Animal {
    override var name: String = "고래"
    override fun eat() {
        Log.d("test", "고래가 먹이를 먹다.")
    }

    override fun move() {
        Log.d("test", "고래가 헤엄쳐 이동하다.")
    }
}

인터페이스에서 재미있는 건 클래스의 상속 형태가 아닌 인터페이스 자체를 그대로 받아 객체를 생성하는 것도 가능하다는 것입니다. 이렇게 하려면 object키워드를 통해 인터페이스를 받아야 합니다.

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        var Whale = object : Animal {
            override var name: String = "고래"
            override fun eat() {
                Log.d("test", "고래가 먹이를 먹다.")
            }

            override fun move() {
                Log.d("test", "고래가 헤엄쳐 이동하다.")
            }
        }
        
        Whale.move()
    }
}

728x90