[Kotlin] 상속

백현균·2023년 4월 16일

1. 추상 클래스

1) 코틀린에서 프로퍼티를 오버라이딩을 해야 할 경우 open키워드를 사용

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(){
    	pritln("고양이!")
    }
}
class Penguin(
	species:String
) : Animal(species, 2){

	private val winCount:Int = 2
	
    override fun move(){
    	pritln("펭귄!")
    }
    
    override val legCount:Int
    	get() = super.legCount + this.winCount
}

2) 자바와 마찬가지로 추상클래스는 인스턴스화 할 수 없음

2. 인터페이스

1) 자바에서의 default키워드 없이 인터페이스의 기본 메소드 구현 가능

2) 추상메소드도 생성 가능

3) 자바에서 상위의 메소드를 호출할 때, super.Method이지만, 코틀린에서는 super<인터페이스명>.Method로 호출

interface Flyable{
	fun act(){
    	println("파닥")
    }
    
   fun fly()
}
interface Swimable{
	func act(){
  	  println("어푸")
    }
}
class Penguin(
	species:String
) : Animal(species, 2), Swimable, Flyable{

	private val winCount:Int = 2
	
    override fun move(){
    	pritln("펭귄!")
    }
    
    override val legCount:Int
    	get() = super.legCount + this.winCount
        
	override fun act(){
    	super<Swimable>.act()
        super<Flyable>.act()
    }
}

4) 자바와 마찬가지로 인터페이스를 인스턴스화할 수 없다

5) backing field가 없는 프로퍼티를 interface에 생성 가능

interface Swimable{
	val swimAlility:Int
	func act(){
  	  println("어푸")
      // 사용 가능
      println(swimAlility)
    }
}
class Penguin(
	species:String
) : Animal(species, 2), Swimable, Flyable{

	private val winCount:Int = 2
	
    override fun move(){
    	pritln("펭귄!")
    }
    
    override val legCount:Int
    	get() = super.legCount + this.winCount
        
	override fun act(){
    	super<Swimable>.act()
        super<Flyable>.act()
    }

	// 굳이 getter에 대한 default메소드, gettger에 대한 
    추상메소드를 만드는 것이기 때문에 가능
    override val swimAlility:Int
    	get() = 3
}

3. 클래스를 상속할 때의 주의점

1) class 앞에 open키워드를 사용할 경우 다른 클래스에서 상속이 가능

2) 상위클래스의 constructor이나 init블록에서 하위 클래스의 필드에 접근하면 안됨 -> 코틀린에선 권장하지 않음

* 하위 클래스의 생성자에서 number값을 할당 하기 전에 상위 클래스 init블록에서 number값을 호출하게 되므로 0이 출력됨

open class Base(
	open val number:Int = 100
){
	init{
    	println("Base class")
        println(number)
    }
}

class Derived(
	override val number:Int
) : Base(number){
	pritln("Derived Class")
}

* 상위 클래스 설계 시 constructor, init 블록에 사용되는 프로퍼티에는 open을 피해야함

잘못사용할 경우 원치 않는 이상한 값이 나올 수 있음

4. 상속 관련 지시어 정리

1) final

- override를 할수 없게하며, default로 보이지 않게 존재 
- 다른클래스에서 상속받게 하려면 open키워드를 명시해야함

2) open

- 클래스간 override를 열어주는 키워드

3) abstract

- 다른 클래스에서 반드시 override해야하는 키워드

4) override

- 상위 객체의 메소드나 변수를 재정의하여 사용

5. 정리

1) 상속 혹은 구현할 때 :을 사용

2) 상위 클래스 상속을 구현할 때 생성자를 반드시 호출

3) override 표시 필수

4) 추상멤버가 아니면 기본적으로 override불가능

* open키워드를 사용해야함

5) 상위 클래스의 생성장, 초기화 블록에서 open 프로퍼티를 사용하면 버그가 발생할 수 있음

0개의 댓글