Post

코틀린 기본5 - Class와 상속

class 생성

코틀린 클래스 파일에 클래스를 생성할 때 class 키워드를 사용한다.
그리고 자바와는 다르게 생성자를 선언할 때 constructor 키워드를 class 명과 함께 작성한다.

1
2
3
4
class Coffee constructor(
  var name: String = "아메리카노",
  var price: Int = 2000, // 후행콤마를 사용하여 여러 줄로 작성할 수 있다.
) {}

이렇게 생성자멤버변수를 동시에 선언할 수 있고, 멤버변수들은 기본값을 지정할 수 있다.
기본 생성자는 컴파일 시점에 자동 생성되기 때문에, constructor 키워드는 생략할 수 있다.

1
2
3
4
5
// constructor 키워드 생략.
class Coffee(
  var name: String = "아메리카노",
  var price: Int = 2000,
) {}

코틀린 클래스 내부의 var 변수는 getter, setter를 자동 지원하고, val 변수는 getter만 지원한다.


class 선언과 사용

코틀린에서 class는 new 키워드를 사용하지 않고 객체 인스턴스를 생성할 수 있다.
또한 위에서 언급한대로 class의 var, val 멤버변수들의 getter, setter는 자동으로 생성된다.
아래는 class 생성자를 호출하는 다양한 방식과 멤버변수를 사용하는 방법이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
// new 키워드 없이 객체 생성
val coffee1 = Coffee() // 기본 생성자로 객체 생성
val coffee2 = Coffee("라떼", 4000) // 생성자 매개변수 값을 지정하여 객체 생성
val coffee3 = Coffee(name = "라떼", price = 4000) // 생성자 매개변수의 이름과 값을 함께 지정하여 객체 생성 

// class의 멤버변수에 아래와 같이 값을 저장한다. 
// set~ 방식으로 저장하진 않지만, 내부적으로 setter 메소드가 호출된다.
coffee1.name = "콜드브루"
coffee1.price = 3000

// class의 멤버변수를 아래와 같이 값을 읽어온다.
// get~ 방식으로 불러오진 않지만, 내부적으로 getter 메소드가 호출된다.
printlns(coffee1.name) // 콜드브루

코틀린에서는 위에 처럼 get~, set~ 메소드를 호출하지 않고 변수를 직접 선언하여 값을 활용하는 방식으로 getter, setter를 사용하게 된다. val로 선언된 변수는 getter만 선언되어 있다.
물론 getter, setter 메소드를 직접 선언하여 커스텀하게 사용할 수도 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
class Coffee(
  var name: String = "",
  var price: Int = 0,
) {
  val brand: String
    get() = "이디야" // 커스텀 getter 선언

  var quantity: Int = 0
    set(value) {
      field = value // field는 해당 프로퍼티를 가리킨다.
      // quantity = value // 프로퍼티에 직접 저장 시 무한루프 발생
    }
}

위에처럼 get(), set() 커스텀 메소드를 변수와 함께 선언하여 커스텀 가능하고, getter/setter 메소드 내부에서 field는 해당 변수를 가리킨다.
만약 field를 사용하지 않고, 변수에 직접 할당하면 set() 이 반복 호출되어 무한루프가 발생할 수 있으니 주의해야 한다.


상속

코틀린의 class는 기본적으로 final로 선언되기 때문에 상속 이 불가능하다.
상속을 허용하려면 classopen 키워드를 사용하여 선언해야 한다.

1
2
3
4
5
6
7
// open이 붙은 class는 하위클래스에서 상속이 가능하다.
open class Dog {
  open var age: Int = 0
  open fun bark() {
    println("멍멍")
  }
}

하위클래스에서 상속을 받기 위해서 클래스 뒤에 : 와 함께 상속받을 클래스를 지정한다.
그리고 부모클래스의 메소드나 변수를 오버라이드 하려면 override 키워드를 사용한다.

1
2
3
4
5
6
7
8
// 변수는 생성자에서 override 키워드와 함께 선언 가능하다.
open class Bulldog(override var age: Int = 0) : Dog() {
  // final 키워드 사용 시 하위 클래스에서 오버라이드 불가능
  final override fun bark() {
    super.bark()
    println("컹컹")
  }
}

위처럼 변수나 메소드를 오버라이드하여 사용 가능하고, final 키워드를 함수에 사용하면 하위클래스에서 오버라이드가 불가능해진다. 부모클래스의 변수나 메소드를 호출할 때는 자바와 동일하게 super 키워드를 사용하면 된다.

클래스는 다중상속이 불가능하다. 부모클래스의 동일한 메소드나 변수가 존재할 경우 컴파일 에러가 발생한다.(다이아몬드 문제)

This post is licensed under CC BY 4.0 by the author.