! 안드 스터디에서 BaseActivity와 BaseFragment에 대해 공부하고 코드를 작성하던 중에 추상 클래스에 대한 나의 무지함에...안타까웠다 사실 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)이다.
위의 코드를 다시 예를 들자면 다음과 같다.
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
}
인터페이스는 밑에서 언급할 추상 클래스와 달리 구현 부분을 가질 수 있고, 구현했을 경우 디폴트 구현으로 적용된다.
인터페이스에서 메서드 및 프로퍼티를 구현하지 않을 경우 구현하는 클래스에서는 반드시 구현해야 한다!
인터페이스를 선언시 다른 인터페이스를 상속 받을 수 있고, 인터페이스는 여러 개를 구현할 수 있다.
미완성 함수 혹은 실행 영역이 없는 함수.
추상 클래스는 일반 클래스와 인터페이스의 특징이 혼합되어 있다.
추상 메소드와 일반 메소드 둘다 사용이 가능하다. 하지만 추상 메소드가 하나라도 있을 경우 그 클래스는 추상클래스가 되어야 한다. 프로퍼티도 마찬가지고
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 해줘야한다.
특정 클래스는 반드시 하나의 추상 클래스만 상속받아야 하고, 추상 클래스가 추상 클래스를 상속받는 것은 가능하다.
이상 정리 끝!