반응형
상속을 다루는 방법
추상 클래스
Java
public abstract class Animal {
protected final String species;
protected final int legCount;
public Animal(String species, int legCount) {
this.species = species;
this.legCount = legCount;
}
abstract public void move();
public String getSpecies() {
return species;
}
public int getLegCount() {
return legCount;
}
}
public class JavaCat extends Animal{
public JavaCat(String species) {
super(species, 4);
}
@Override
public void move() {
System.out.println("고양이가 걷는다.");
}
}
Kotlin
abstract class Animal(
protected val species: String,
protected open val legCount: Int
) {
abstract fun move()
}
class Cat(species: String) : Animal(species, 4) {
override fun move() {
println("고양이가 걷는다.")
}
}
- 코틀린에서 상속은 extends 키워드를 사용하지 않고
:
를 사용한다.- 변수의 타입을 지정하는 것과 다르게 앞뒤로 띄어쓰기를 해야 한다.
- 추상 클래스를 상속받을 시 상위 클래스의 생성자를 바로 호출해야 한다.
override
를 필수적으로 붙여 함수를 상속받는다.- 코틀린에서 추상 멤버가 아닌 멤버를
override
할 때에는 무조건open
을 붙여주어야 한다. override
키워드와custom getter
을 사용해서 추상클래스에서 만들어진 프로퍼티를override
할 수 있다.
인터페이스
Java
public interface JavaFlyable {
default void act() {
System.out.println("파닥 파닥");
}
}
public interface JavaSwimable {
default void act() {
System.out.println("어푸어푸");
}
}
public class JavaPenguin extends Animal implements JavaFlyable, JavaSwimable{
private final int wingCount;
public JavaPenguin(String species) {
super(species, 2);
this.wingCount = 2;
}
@Override
public void move() {
System.out.println("펭귄이 움직인다.");
}
@Override
public int getLegCount() {
return super.getLegCount() + this.wingCount;
}
@Override
public void act() {
JavaSwimable.super.act();
JavaFlyable.super.act();
}
}
Kotlin
interface Flyable {
fun act() {
println("파닥 파닥")
}
}
interface Swimable {
val swimAbility: Int
fun act() {
println("어푸 어푸")
}
}
class Penguin(species: String) : Animal(species, 2), Swimable, Flyable {
private val wingCount: Int = 2
override fun move() {
println("펭귄이 움직인다.")
}
override val legCount: Int
get() = super.legCount + this.wingCount
override fun act() {
super<Swimable>.act()
super<Flyable>.act()
}
override val swimAbility: Int
get() = 3
}
- 인터페이스 구현도
implement
가 아닌:
를 사용한다. - 코틀린의 인터페이스에서
default
메서드를 구현할 때default
키워드 없이 메서드 구현이 가능하다. - 코틀린에서도 추상 메서드를 만들 수 있다.
- 중복되는 인터페이스를 특정할 때에는
super<타입>.함수
를 사용한다. - 코틀린에서는
backing field
가 없는 프로퍼티를interface
안에 만들 수 없다.- 인터페이스에 필드를 생성하였다면 해당 인터페이스에서 get()을 구현하거나, 상속받은 구현체에서
get()
을override
해주어야 한다. - 위 코드에서 swimAbility의 경우 인터페이스에서
get
을 구현하지 않았기 때문에 구현한 Penguin에서 swimAbility를override
하여 구현했다.
- 인터페이스에 필드를 생성하였다면 해당 인터페이스에서 get()을 구현하거나, 상속받은 구현체에서
클래스를 상속할 때 주의할 점
Kotlin
fun main() {
Derived(32)
}
open class Base(
open val number: Int = 100
) {
init {
println("Base Class")
println(number)
}
}
class Derived(
override val number: Int
) : Base(number) {
init {
println("Derived Class")
}
}
- 위 코드를 보면 Derived를 인스턴스화 할 때 Base의 생성자를 먼저 부른 후, init 실행, 그 다음에 Derived의 init을 실행한다.
- 문제는 Base의
println(number)
에 있다. - number 프로퍼티는 Derived에서 상속받았기 때문에 Base의 init에서 사용한 number은 자식인 Derived의 number을 이용한다.
- 하지만 Base의 생성자가 먼저 호출되어 Base.init에 있는 number은 아직 초기화되지 않은 number이다.
- 때문에 0이 출력된다.
- 상위 클래스를 설계할 때 생성자 또는 초기화 블록에 사용되는 프로퍼티에는 open을 피해야 한다.
상속 관련 지시어
final
:override
를 할 수 없게 한다.default
로 보이지 않고 존재한다.open
:override
를 열어준다.abstract
: 반드시override
해야 한다.override
: 상위 타입을 오버라이드 하고 있다.
반응형
'Java & Kotlin > Kotlin' 카테고리의 다른 글
[Kotlin] 중첩 클래스를 다루는 방법 (0) | 2022.07.06 |
---|---|
[Kotlin] object를 다루는 방법 (0) | 2022.07.06 |
[Kotlin] 접근제어를 다루는 방법 (0) | 2022.07.06 |
[Kotlin] 클래스를 다루는 방법 (0) | 2022.07.06 |
[Kotlin] 함수를 다루는 방법 (0) | 2022.07.06 |
[Kotlin] 예외를 다루는 방법 (0) | 2022.07.06 |