+ 항공대학교 김철기 교수님의 객체 지향 프로그래밍 과목 내용를 정리한 글입니다.
하위 클래스 선언
상위 클래스 = 부모 클래스 = Super Class
하위 클래스 = 자식 클래스 = Sub Class
ex) Activiy - MainActivity , Vehicle - FlyingVehicle - Aircraft
+ 하나의 클래스는 하나의 상위 클래스를 가질 수 있다.
open 클래스
open으로 선언된 클래스는 상속이 가능하다.
- open이 아닌 클래스는 상속이 불가능하다.
: 뒤의 상위 클래스 ()는 상위 클래스 생성자 호출을 의미한다.
- 필수적으로 상위 클래스의 생성자를 사전에 호출해야한다.
하위 클래스 객체는 모두 상위 클래스에도 소속된다.
멤버의 상속
-하위 클래스는 상위 클래스의 멤버를 모두 상속한다.
// open을 선언한 클래스만 상속 가능
open class Vehicle {
var currentSpeed = 0
fun start() {
println("I'm moving")
}
fun stop() {
println("Stopped")
}
}
open class FlyingVehicle : Vehicle() {
fun takeOff() {
println("Taking off")
}
fun landing() {
println("Landed")
}
}
class Aircraft(val seats: Int) : FlyingVehicle()
fun main() {
val aircraft = Aircraft(100)
val vehicle: Vehicle = aircraft // 상위 타입 변수에 하위 타입을 대입할 수 있다.
vehicle.start()
vehicle.stop()
vehicle.takeoff() // 에러 발생
aircraft.start()
aircraft.takeOff()
aircraft.landing()
aircraft.stop()
println(aircraft.seats)
}
멤버 상속 구현 (다형성, Polymorphism)
상위 클래스의 open 멤버를 override하여 구현을 수정할 수 있다.
open class Vehicle {
var currentSpeed = 0
open fun start() {
println("I'm moving")
}
fun stop() {
println("Stopped")
}
}
class Car : Vehicle() {
override fun start() {
println("I'm riding")
}
}
class Boat : Vehicle() {
override fun start() {
println("I'm sailing")
}
}
fun main() {
val vehicle1: Vehicle = Car()
val vehicle2: Vehicle = Boat()
// 변수의 타입보다 실제 객체의 타입이 더 중요하다!
vehicle1.start() // I'm riding
vehicle2.start() // I'm sailing
}
확장과 상속(override)의 차이
상속: 인스턴스의 실제 타입으로 호출 대상이 결정된다.
확장: 변수의 타입에 따라 정적으로 호출 대상이 결정된다.
open class Vehicle {
var currentSpeed = 0
open fun start() {
println("I'm moving")
}
}
fun Vehicle.stop() {
println("Stopped")
}
class Car : Vehicle() {
override fun start() {
println("I'm riding")
}
}
fun Car.stop() {
println("Stopped riding")
}
class Boat : Vehicle() {
override fun start() {
println("I'm sailing")
}
}
fun main() {
val car: Car = Car()
val vehicle1: Vehicle = Car()
val vehicle2: Vehicle = Boat()
// 변수의 타입보다 실제 객체의 타입이 더 중요하다!
vehicle1.start() // I'm riding
vehicle2.start() // I'm sailing
// 변수의 타입에 맞는 함수를 호출한다. (확장)
vehicle1.stop() // Stopped (Vehicle 타입 변수 -> Vehicle 객체 내 함수 호출)
vehicle2.stop() // Stopped
car.start()
car.stop() // Stopped riding (Car 타입 변수 -> Car 객체 내 함수 호출)
}
상속과 멤버 시그니처
상속하는 멤버의 시그니처와 상위 클래스 멤버 시그니처는 동일해야한다.
시그니처: 파라미터들의 순서, 타입과 반환 값 타입
open class Vehicle {
var currentSpeed = 0
open fun start(speed: Int) {
println("I'm moving at $speed")
}
fun stop() {
println("Stopped")
}
}
class Car : Vehicle() {
override fun start(speed: Int) { // Vehicle 클래스의 start 함수의 시그니처와 동일
println("I'm riding at $speed")
}
}
fun main() {
val car: Car = Car()
val vehicle: Vehicle = car
vehicle.start(100)
vehicle.stop()
car.start(100)
car.stop()
}
final을 통한 추가 상속의 제한
override한 멤버는 open을 선언하지 않아도 추가 상속을 할 수 있다.
open class Vehicle {
var currentSpeed = 0
open fun start() {
println("I'm moving")
}
fun stop() {
println("Stopped")
}
}
open class Car : Vehicle() {
override fun start() { // open을 선언하지 않아도 상속 가능
println("I'm riding")
}
}
class Bus : Car() {
override fun start() {
println("I'm riding a bus")
}
}
override하는 멤버를 final로 선언하면 추가 상속을 할 수 없다.
open class Vehicle {
var currentSpeed = 0
open fun start() {
println("I'm moving")
}
fun stop() {
println("Stopped")
}
}
open class Car : Vehicle() {
final override fun start() { // final 선언
println("I'm riding")
}
}
class Bus : Car() {
override fun start() { // Car의 start 함수 추가 상속 불가 -> 에러
println("I'm riding a bus")
}
}
프로퍼티의 상속
주생성자 파라미터를 통해 하위 클래스 본문에 구현을 넣어 상속 가능하다.
open class Entity {
open val name: String
get() = ""
}
class Person(override val name: String) : Entity()
fun main() {
val person: Person = Person("Sangsin")
println(person.name)
}
불변 프로퍼티를 가변 프로퍼티로 상속 가능하다. (반대는 불가능)
open class Entity {
open val name: String
get() = ""
}
class Person() : Entity() {
override var name = ""
}
fun main() {
val person: Person = Person()
person.name = "Sangsin"
println(person.name)
}
protected 접근 제어자
protected를 통해 상속 체계 밖에서의 멤버 접근을 막을 수 있다.
open class Vehicle {
protected open fun onStart() {}
fun start() {
println("Starting up ...")
onStart()
}
}
class Car : Vehicle() {
override fun onStart() {
println("It's a car")
}
}
fun main() {
val car = Car()
car.start()
car.onStart() // main 함수는 클래스 밖에 있으므로 접근 불가
}
'Study > Kotlin Study' 카테고리의 다른 글
[Kotlin] 타입 검사와 캐스팅 (2) | 2023.10.23 |
---|---|
[Kotlin] 하위 클래스 초기화 (0) | 2023.10.23 |
[Kotlin] Fragment 실습 (2) | 2023.10.14 |
[Kotlin] 영역 함수 (0) | 2023.10.09 |
[Kotlin] 확장 (0) | 2023.10.09 |