1. 클래스 간 상속
- ":"을 써서 상속받는다
- 부모 클래스가 생성자 매개변수를 가지고 있다면, 자식 클래스가 상속할 때 그 매개변수를 반드시 전달해야 한다. 매개변수가 없다면 그냥 () 쓰면 된다.
- 부모 클래스 쪽에 open 키워드를 앞에 붙여줘야 한다.
// 부모 클래스
open class Animal(val name: String, val age: Int) {
fun introduce() {
println("저는 $age살 $name입니다.")
}
}
그 뒤 자식 클래스를 작성해 보자
// 자식 클래스
class Dog(name: String, age: Int) : Animal(name, age) {
fun bark() {
println("멍멍!")
}
}
이걸 메인함수에서 실행해 보자
fun main() {
val myDog = Dog("초코", 3)
myDog.introduce() // 저는 3살 초코입니다.
myDog.bark() // 멍멍!
}
이런 식으로 클래스의 상속을 구현한다.
2. 인터페이스
- 자바는 implements를 쓰지만 코틀린은 : 을 쓴다
- 코틀린의 인터페이스 안에는 추상 메서드 뿐 아니라 구현이 있는 메서드도 정의할 수 있다
- 자바에선 프로퍼티 선언이 불가능하지만 코틀린은 프로퍼티 선언이 가능하다
- 클래스 상속 시에는 ()을 쓰지만 인터페이스는 안 쓴다
- 인터페이스의 메서드 구현 시에는 override키워드를 꼭 붙여야 한다!!
우선 인터페이스를 선언해 보자.
interface Soccer {
fun kick()
}
그 다음으로 이 인터페이스를 구현해 보자
class Player() : Soccer {
override fun kick() {
println("공을 찬다.")
}
}
또한 인터페이스에 구현이 있는 메서드도 다음과 같이 정의할 수 있다.
interface Soccer {
fun kick()
fun throwIn() = println("공을 양손으로 던진다.")
fun tackle() {
println("공을 뺏기 위해 다리를 뻗는다.")
}
}
인터페이스에 구현부가 있는 메서드는 다음 코드처럼 굳이 오버라이드하여 구현하지 않아도 된다.
interface Soccer {
fun kick()
fun throwIn() = println("공을 양손으로 던진다.")
fun tackle() {
println("공을 뺏기 위해 다리를 뻗는다.")
}
}
class Player() : Soccer {
override fun kick() {
println("공을 찬다.")
}
}
이번엔 코틀린의 프로퍼티 선언에 대해 알아보자
interface Soccer {
val ball: Ball
fun kick()
fun throwIn() = println("공을 양손으로 던진다.")
fun tackle() = println("공을 뺏기 위해 다리를 뻗는다.")
}
class Ball() {
var posX: Int = 0
var posY: Int = 0
}
이런 식으로 인터페이스 안에 프로퍼티를 선언할 수 있다. 하지만 인터페이스 안에서 초기화까진 불가능하다. 즉 필드는 가질 수 없다.
// Soccer 인터페이스 구현 클래스
class Player : Soccer {
override val ball = Ball() //Ball 객체를 하나 만들어서 ball 프로퍼티로 설정
override fun kick() {
ball.posX += 10
ball.posY += 5
println("공을 찼습니다! 위치: (${ball.posX}, ${ball.posY})")
}
}
// main 함수에서 테스트
fun main() {
val player = Player()
player.kick() // 공을 찼습니다! 위치: (10, 5)
player.throwIn() // 공을 양손으로 던진다.
player.tackle() // 공을 뺏기 위해 다리를 뻗는다.
}
이렇게 구현하면 된다.
class Player(override val ball: Ball) : Soccer {
override fun kick() {
println("공을 찬다.")
}
}
fun main() {
val sharedBall = Ball()
val player = Player(sharedBall)
println(player.ball.posX) // 0
player.kick() // 공을 찬다.
}
이런 식으로 생성자 매개변수에서 바로 받아서 구현하는 것도 가능하다.(이게 더 중요한듯..)
3. 여러 인터페이스 동시 구현
코틀린도 자바와 마찬가지로 클래스는 하나의 상위 클래스만 상속 받을 수 있으며 여러 상위 인터페이스를 개수 제한 없이 구현할 수 있다.
우선 이렇게 두 인터페이스를 만들어 보자
interface Soccer {
val ball: Ball
fun kick() = println("공을 찬다.")
fun throwIn() = println("공을 양손으로 던진다.")
fun tackle()
}
interface Taekwondo {
val state: State
fun kick() = println("발차기를 한다.")
fun guard()
}
그다음 이 인터페이스를 동시 구현해 보자
class Player(override val ball: Ball, override val state: State) : Soccer, Taekwondo {
override fun tackle() {
println("공을 뺏기 위해 다리를 뻗는다.")
}
override fun guard() {
println("몸을 방어한다.")
}
}
이렇게 했더니 오류가 난다. 그 이유는 kick이 인터페이스 단계에서 구현 되어있긴 하지만 두 인터페이스에 같은 이름의 kick메서드가 있기 때문이다. 이런 경우 kick 메서드의 구현을 강제한다.
class Player(override val ball: Ball, override val state: State) : Soccer, Taekwondo {
override fun tackle() {
println("공을 뺏기 위해 다리를 뻗는다.")
}
override fun guard() {
println("몸을 방어한다.")
override fun kick() {
println("찬다.")
}
}
이렇게 kick을 구현해주면 오류가 사라진다.
그렇다면 super키워드를 사용하여 상위 타입의 메서드를 사용하고 싶다면 어떻게 해야할까?
super와 꺽쇠(<>)를 이용해 사요할 수 있다.
override fun kick() {
super<Soccer>.kick()
super<Taekwondo>.kick()
}
이렇게 하면 된다.
'안드로이드 스터디' 카테고리의 다른 글
| RecyclerView를 써 보자! (0) | 2025.11.02 |
|---|---|
| 뷰페이저2를 만들어 보고 탭 레이아웃과 연동시켜보자! (0) | 2025.11.01 |
| HomeFragment.kt 분석 (0) | 2025.11.01 |
| 메인액티비티 코드 분석 (0) | 2025.11.01 |
| 코틀린 기본 문법 정리 - 익명클래스와 익명객체 (0) | 2025.11.01 |