매일 한줄 코딩

#7. 코틀린 상속 - Inheritance 본문

develop/kotlin

#7. 코틀린 상속 - Inheritance

ShipJH 2022. 6. 6. 23:27
7. 상속 - Inheritance

7. 상속 - Inheritance


1. 상속 - 최상위 클래스 Any

  • 클래스에 상위타입을 선언하지 않으면 Any가 상속됨
  • 코틀린의 최상위 클래스는 Any이다.
class Test1 // 암시적인 Any상속
class Test2 : Any() // 명시적인 Any상속
// java의 extend 대신 콜론(:) 을 쓴다.

  • Any는 java.lang.Object와는 다른 클래스이다.
    • equals(), hashCode(), toString() 만 있다.
package kotlin

public open class Any {
   
    public open operator fun equals(other: Any?): Boolean

    public open fun hashCode(): Int

    public open fun toString(): String
}


2. 상속 - 특징

  • 명시적으로 상위타입을 선언하려면, 클래스 해더의 콜론 뒤에 상위타입을 선언하면 됨.
  • 파생클래스에 기본생성자가 있으면 파생클래스의 기본생성자에서 상위타입의 생성자를 호출해서 초기화 할 수 있다.
//상속을 해줄 클래스가 open을해주어야 다른 클래스가 상속을 받을 수 있다.
open class AA(x: Int)

// 파생클래스 (상속받을 클래스)
// 상속받을 클래스 : 상위타입 	
// 상속받을 클래스에 기본생성자가 있으면 상위타입의 생성자를 호출해서 초기화 할 수 있음.
class BB(x: Int) : AA(x)

  • 파생클래스에 기본생성자가 없으면,
  1. 각각의 보조생성자에서 상위타입 super 키워드를 이용해서 초기화 해주어야 하거나,
  1. 다른 생성자에게 상위타입 초기화를 할 수 있게 위임하여야 한다.
// 파생클래스에 기본생성자가 없다.
class Myview : View {
	constructor() : super(1) // 1. super를 이용한 상위타입을 초기화

	constructor(x: Int) : this() // 2. 위에 생성자에게 상위타입 초기화하도록 위임

	constructor(x: Int, y: Int) : super(x,y) // 1.super를 이용한 상위타입 초기화
}


3. 상속 - open

  • open class는 다른 클래스가 상속 할 수 있다.
  • 기본적으로 코틀린의 모든 class는 final 임. (open 어노테이션은 Java의 final과 반대.)
open class AA(x: Int)


4. 오버라이딩

4-1. 메소드 오버라이딩

  • 오버라이딩 될 메소드 → open 키워드 필요
  • 오버라이딩 된 메소드 → override 키워드 필요
open class AA {
	open fun hi() {} // open 키워드가 필요. 오버라이딩 해주려면..
	fun bye()
}

class BB() : AA() {
	override fun hi() {} // 오버라이딩 하려면 override 키워드 필요.
}

자바같았으면, 그냥 상속받으면 hi()를 가져다가 오버라이딩 가능했지만 코틀린은 키워드를 달아주어야 한다.

4-2. 프로퍼티 오버라이딩

  • 메소드 오버라이딩과 유사한 방식으로 한다.
  • 오버라이딩 될 프로퍼티 → open 키워드 필요
  • 오버라이딩 된 프로퍼티 → override 키워드 필요
open class AA {
	open val x: int get {...}
}

class BB: AA() {
	override val x : Int = ...
}

4-3. 오버라이딩 규칙

  • 같은 멤버에 대한 중복된 구현상속을 받은 경우 상속 받은 클래스는 해당 멤버를 오버라이딩하고 자체 구현을 제공해야 한다.
  • super + <클래스> 를 통하여 상위 클래스의 메소드를 호출 할 수 있다.
  • 자바처럼 클래스 1개 상속받고, 여러개의 인터페이스를 상속 받을 수 있다.
open class A {
	open fun f() { print("A") }
	fun a() { print("a") }
}

interface B {
	fun f() { print("B") }
	fun b() { print("b") }
}

class C() : A(), B { 
	
/* 
 중복된 구현상속 f() 을 받은 경우 
 상속받은 클래스는 해당 멤버를 오버라이딩하고,
 자체 구현을 제공해야 한다.
*/
	override fun f() {
		/* 자체 구현이 필요하다. 안하면 컴파일 에러. */

		super<A>.f() // call to A.f()
		super<B>.f() // call to B.f()
	}
}

즉, 모호성을 없애면 된다.


5. 추상클래스

  • abstract 멤버는 구현이 없음
  • abstract 클래스나 멤버는 open이 필요 없음 (기본적으로 open이 되어있음)
abstract class AA() {
	abstract fun f() // 구현부가 없음.
}

class MyClass() : AA {
	override fun() { /* 상속 받아 구현*/ }
}

Comments