231216 TIL #270 Kotlin #5 클래스 / 인터페이스

김춘복·2023년 12월 16일
0

TIL : Today I Learned

목록 보기
270/543
post-custom-banner

Today I Learned

Kotlin in Action 계속 공부중..


클래스 계층 정의

코틀린 인터페이스

코틀린의 인터페이스는 Java 8 인터페이스와 비슷하다.
추상메서드 뿐만 아니라 구현이 있는 메서드(자바의 디폴트 메서드와 비슷)도 정의할 수 있다.

  • 예시
    click() 추상메서드를 정의. 이 인터페이스를 구현하는 클래스는 이 추상 메서드에 대한 구현을 해야한다.
interface Clickable{
    fun click()
}

class Button : Clickable {
    override fun click() = println("click!")
}
  • 자바에서는 extends, implements 키워드를 쓰지만, 코틀린에서는 : 콜론으로 다 처리한다.
    다만 클래스는 뒤에 괄호()가 붙고(괄호안에는 생성자용 파라미터), 인터페이스는 붙지 않는다.

  • 자바와 마찬가지로 클래스는 인터페이스를 원하는 만큼 구현 가능하지만, 클래스는 하나만 상속가능하다.

  • override : 자바에서는 @Override 애너테이션을 쓰지만 코틀린에서는 변경자로 메서드 앞에 반드시 써야한다.

  • 인터페이스에서 디폴트 메서드를 정의할 경우 구현하는 클래스에서 새로운 동작을 정의하거나, 정의를 생략해서 그대로 사용할 수 있다.

  • 인터페이스 2개를 상속하는 클래스에서 중복된 이름의 디폴트 메서드가 있을 경우 super<인터페이스명>.메서드명 으로 상위 타입 메서드를 구현해야한다.


상속과 구현

  • 취약한 기반 클래스(fragile base class) 문제

    Java에서는 final이 아닌 모든 클래스는 상속이 가능하다.
    상속 시, 기반 클래스가 변경될 시 하위 클래스의 동작이 예기치 않게 바뀔 수 있다.
    모든 기반 클래스 변경 시 하위클래스를 미리 파악하는 것은 힘드므로,
    [Effective Java]에서는 상속을 위한 설계와 문서를 갖추거나 아니면 상속을 금지하라 는 조언이 있다.

  • 코틀린에선 기본적으로 모든 클래스와 메서드가 final이다.

  • 그러므로 클래스의 상속을 허용하려면 open 변경자를 붙여야 한다.

  • 오버라이드를 허용할 메서드나 프로퍼티도 open을 붙여야 한다.
    이미 오버라이드 한 메서드는 open 상태이다. 하지만 이 메서드를 오버라이드 다시 금지하려면 final을 메서드에 명시하면 된다.(final override fun ~)

추상클래스

abstract class Animated { // 추상크랠스. 인스턴스 생성 불가
	abstract fun animated()	// 추상 메서드. 하위 클래스에서 반드시 구현해야
    open fun stopAnimating(){ //추상클래스이지만 비추상 메서드. 오버라이드 가능
    }
    fun animateTwice(){  //추상클래스이지만 비추상 메서드. 오버라이드 불가능
    }
}

상속 및 오버라이드 정리

클래스 : 기본적으로 상속이 불가능한 final. open을 붙여야 오버라이드 가능
인터페이스 : 기본적으로 모든 멤버가 open. 반드시 오버라이드 해야 함.
추상클래스 : abstract(추상)메서드는 반드시 오버라이드 해야함. 나머지 멤버는 기본적으로 final

제어자 정리

변경자상태설명
final오버라이드 불가클래스 멤버의 기본 변경자
open오버라이드 가능반드시 open을 명시해야 오바라이드 가능
abstract반드시 오버라이드 해야함추상클래스 멤버에만 붙일 수 있음
override이미 오버라이드 하는 상태이 멤버의 오버라이드를 금지하려면 final 붙여야함
  • 접근 제어자 정리
    자바(default, 같은 패키지)와는 다르게 코틀린에서 기본 가시성은 public이다.
    코틀린에선 internal을 사용하는데, 이는 같은 모듈 안에서만 볼 수 있음을 뜻한다.
    모듈은 컴파일 시에 컴파일러에 의해 정의되는 개념으로, 보통은 프로젝트 내의 한 단위를 나타낸다.
    그리고 자바에서 protected는 패키지 멤버도 허용됐지만, 코틀린에선 해당 클래스나 상속받은 클래스만 볼 수 있다.
변경자클래스 멤버최상위 선언
public(기본)모든 곳에서 볼 수 있음모든 곳에서 볼 수 있음
internal같은 모듈 안에서만 볼 수 있음같은 모듈 안에서만 볼 수 있음
protected하위 클래스 안에서만 볼 수 있음최상위 선언에 적용 불가능
private같은 클래스 안에서만 볼 수 있음같은 파일 안에서만 볼 수 있음

중첩클래스(nested class)

자바처럼 코틀린에서도 클래스 안에 다른 클래스를 선언할 수 있다.
하지만 자바랑은 다르게 코틀린에선 명시적으로 요청하지 않는 한 바깥쪽 클래스 인스턴스에 대한 접근권한이 없다.

  • 코틀린 중첩 클래스에 아무런 제어자가 붙지 않으면 자바 static 중첩 클래스와 같다.

  • 중첩 클래스 앞에 inner 제어자를 붙이면 내부 클래스로 변경되어 바깥 클래스의 참조를 포함할 수 있다.
    this@Outer로 바깥쪽 클래스의 참조에 접근 가능하다.

sealed class

클래스의 서브클래스들을 제한하는 역할을 하는 클래스

  • 클래스 선언 앞에 sealed 제어자를 붙인다.
sealed class Shape {
    class Circle(val radius: Double) : Shape()
    class Square(val sideLength: Double) : Shape()
    class Triangle(val base: Double, val height: Double) : Shape()
}
  • sealed class의 서브클래스는 반드시 같은 파일 내에서 선언되어야 한다. 서브클래스의 종류가 제한적이고 한정적임을 의미한다.

  • 클래스 외부에 자신을 상속한 클래스를 둘 수 없다.

  • 이를 통해 when 식 등에서 모든 경우를 고려할 수 있어 별도의 else분기가 필요없고, 특정 클래스 계층의 종류가 변경되더라도 놓치는 경우를 방지할 수 있다.


profile
Backend Dev / Data Engineer
post-custom-banner

0개의 댓글