클래스와 상속

클래스

  • class 키워드를 사용하여 선언
  • 헤더와 본문은 옵션. 본문이 없는 경우 중괄호 생략 가능
class Invoice {
}

생성자

  • 기본 생성자하나이상의 보조 생성자를 가질 수 있다
  • constructor 키워드 생략 가능
  • 기본값을 가질 수 있음
class Person(val firstName: String = "") {
}

//  class Person constructor(firstName: String) {
//  }
  • 초기하는 init 키워드를 이용
class Customer(name: String) {
    init {
        logger.info("Customer initialized with value ${name}")
    }
}
  • 기본 생성자의 파라매터를 프로퍼티 초기화에 사용 가능
class Customer(name: String) {
    val customerKey = name.toUpperCase()
}
  • 어노테이션 / 가시성 제한자를 가지는 경우 constructor 키워드가 필요
class Customer public @Inject constructor(name: String) { ... }

가시성 제한자 참고

보조 생성자

  • constructor 키워드를 이용하여 보조 생성자 선언 가능
  • 생성자 오버라이딩은 this 키워드를 이용
class Person(val name: String) {
    constructor(name: String, parent: Person) : this(name) {
        parent.children.add(this)
    }
}
  • 공개 생성자를 원하지 않으면 private constructor 사용
class DontCreateMe private constructor () {
}

클래스 인스턴스 작성

  • new 키워드가 존재하지않음
val invoice = Invoice()

val customer = Customer("Joe Smith")

상속

  • 모든 클래스에는 공통의 Any 슈퍼 클래스가 존재
    • Any != java.lang.Object
    • equals(), hasCode(), toString()
class Example // Implicitly inherits from Any

자바 상호 운용 참고

  • 상속 선언
open class Base(p: Int)
class Derived(p: Int) : Base(p)
  • 주요 기본 생성자가 없는 경우는 super 키워드를 사용해서 기본타입 초기화 혹은 다른 생성자에게 위임
class MyView : View {
    constructor(ctx: Context) : super(ctx)

    constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs)
}
  • open 어노테이션은 자바의 final과 반대
    • 기본적인 코틀린의 클래스는 final
    • Effective Java 의 Item 17 : Design and document for inheritance or else prohibit it 내용에 의거

메소드 오버라이딩

  • 오버라이드 멤버를 명시적으로할 필요
    • open : override 가능한 멤버 지정
    • override : override 한 멤버 지정
  • final 클래스에서는 open 멤버가 금지
  • override를 명시한 멤버는 open이다. 오버라이딩을 막고 싶으면 final 을 사용
open class Base {
    open fun v() {}
    fun nv() {}
}
class Derived() : Base() {
    override fun v() {}
}
open class AnotherDerived() : Base() {
    final override fun v() {}
}

Derived.v() 에 override 어노테이션을 붙이지 않으면 컴파일 에러 발생

프로퍼티 오버라이딩

  • 메소드 오버라이드와 동일한 매커니즘
  • val 프로퍼티를 var 프로퍼티로 오버라이딩 가능. 그 반대는 불가능

오버라이딩 규칙

  • 동일한 함수를 override 하는 경우 super<Base> 으로 호출 가능
open class A {
    open fun f() { print("A") }
    fun a() { print("a") }
}

interface B {
    fun f() { print("B") } // interface는 기본으로 open
    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()
    }
}

추상 클래스

  • 클래스와 메소드를 abstract로 선언
  • 추상 메소드는 구현을 가지지 않는다
  • open을 붙일 필요 없다
  • 비상적인 공개 메소드를 추상 메소드로 override 가능
open class Base {
    open fun f() {}
}

abstract class Derived : Base() {
    override abstract fun f()
}

Companion Objects

  • Kotlin에서는 정적 메소드는 없음 → 패키지 레벨의 함수 사용을 권장
  • 클래스 내부에 접근할 필요가 있는 함수를 작성할 경우 (예. 팩토리 메소드)에는 클래스 내의 선언한 오브젝트의 멤버로 기술가능
    • 클래스 내에 Companion Object를 선언함으로 클래스명으로 Java/C#의 정적 메소드 호출과 같은 구문으로 멤버 호출이 가능

results matching ""

    No results matching ""