파게로그
[OOP] Abstract class, Interface 본문
Kotlin에서 abstract 키워드는 추상 클래스를 선언하기 위해 사용된다. 추상 클래스는 초기화될 수 없다. 즉 추상 클래스의 객체를 생성하는 것은 불가능하다. 그러나 추상 클래스를 상속받는 것은 가능하다.
properties, methods 등, 추상 클래스의 멤버는, abstract 키워드를 사용하지 않는 한 abstract하지 않다.
abstract class Person(name: String = "Unknown", age: Int = 0) {
var name = name
var age = age
abstract fun describe()
fun introduce() {
println("I am $name and $age years old.")
}
}
class Student(name: String, age: Int, school: String = "Unknown"): Person(name, age) {
var school = school
override fun describe() {
println("I am $name and $age years old and in $school.")
}
}
fun main() {
// var person = Person() // cannot create object of abstract class
var student = Student("Elsa", 16, "Winter School")
student.introduce()
student.describe()
}
여기서 non-abstract property인 name, age나 non-abstract method인 introduce()를 subclass에서 오버라이드하고싶다면, 이들은 open 키워드로 표지되어야 한다.
abstract method인 describe()는 구현체가 없으며 반드시 subclass에서 오버라이드되어야 한다.
abstract class는 언제나 open이므로 open 키워드를 명시할 필요는 없다.
한편 인터페이스는 추상 클래스와 비슷한 점도 있지만, 추상 클래스와 달리 상태를 저장할 수 없다는 차이점을 지니기도 한다.
인터페이스는 property를 가질 수는 있지만 abstract여야 하거나, 또는 accessor의 구현 제공이 필요하다. 하지만 추상 클래스의 property는 반드시 abstract여야 하는 것은 아니다.
Kotlin에서 인터페이스를 정의하는 키워드는 interface이다. 아래 코드에서, Pants는 Wearable 인터페이스를 구현한다. 즉 abstract members인 size property와 wear function을 오버라이드했다.
interface Wearable {
var size: Char
fun wear()
fun sizeUp() {
size = size.inc()
println("size up: ${size.dec()} -> ${size}")
}
}
class Pants: Wearable {
override var size = 'C'
override fun wear() {
println("Put pants on...")
}
}
fun main() {
var pants = Pants()
pants.wear()
pants.sizeUp()
}
실행 결과는 다음과 같다.
Put pants on...
size up: C -> D
한편 인터페이스는 accessor의 구현을 제공하는 property 또한 가질 수 있다. 예를 들면 다음과 같다.
interface MyInterface {
// property with implementation
val prop: Int
get() = 23
}
class InterfaceImp : MyInterface {
// ...
}
fun main(args: Array<String>) {
val obj = InterfaceImp()
println(obj.prop)
}
실행 결과는 다음과 같다.
23
prop은 abstract가 아니다. 그러나 이는 accessor의 구현체를 제공하기에 인터페이스 내부에서 유효하다. 하지만 인터페이스 내에서 val prop: Int = 23과 같은 동작을 수행할 수는 없다.
다수의 인터페이스 구현하기
Kotlin은 다중 상속을 허용하지 않지만, 단일 클래스가 두 개 이상의 인터페이스를 구현하는 것은 허용한다.
class Child: A, B
이 때 오버라이딩 과정에서 충돌이 발생할 수 있다. 두 개의 인터페이스가 같은 non-abstract method를 가지고 있다면.. 이 때에는 메서드를 호출하면 에러가 발생한다. 해결을 위해서는 고유한 구현을 제공해야 한다. 예를 들면 다음과 같다.
interface A {
fun callMe() {
println("From interface A")
}
}
interface B {
fun callMe() {
println("From interface B")
}
}
class C: A, B {
override fun callMe() {
super<A>.callMe()
super<B>.callMe()
}
}
fun main(args: Array<String>) {
val obj = C()
obj.callMe()
}
'콤퓨타 왕기초 > Kotlin' 카테고리의 다른 글
[OOP] Data Class (0) | 2021.06.13 |
---|---|
[OOP] Nested class and Inner class (0) | 2021.06.13 |
[OOP] Visibility Modifiers (0) | 2021.06.12 |
[OOP] inheritance (0) | 2021.06.12 |
[OOP] Getters and Setters (0) | 2021.06.11 |