2022.04.24 - [개발 지식/Kotlin] - [Kotlin] Kotlin 기초 -01
08. Class, Method
Kotlin 기초 - 01 에서 class 관련하여 class 작성 및 생성자 생성까지 정리했다면 이번에는 상속 관련하여 적어보려고 한다.
08 - 1. 상속
자바 언어의 특징 중 하나인 상속은 코틀린에서도 그대로 적용 가능하다. 상속은 말 그대로 부모 클래스(수퍼클래스)와 자식클래스(서브클래스)로 이루어져 있으며 서브 클래스는 수퍼클래스을 상속 받아 로직을 수행한다.
즉 서브클래스는 수퍼클래스의 같은 이름의 속성이 존재할 수 없으며 수퍼 클래스 생성까지 진행한다.
상속 관련하여 자바와 코틀린의 가장 큰 차이점은 코틀린은 클래스의 상속 금지가 기본값이라는 것이다
Java :
public class Person {
// TODO
}
public class Man extends Person {
// TODO
}
Kotlin :
class Peson() {
// TODO
}
class Man : Peson() {
// TODO
}
Man 클래스가 Person 클래스를 상속받으려고 하면 다음과 같은 오류가 발생한다.
이에 코틀린은 클래스 앞에 open 선언을 해주어야 한다.
open class Food(var kindValue: String, var name: String, var kcal: String) {
fun introduce() {
println("${kindValue}의 종류 중 하나인 ${name}는/은 ${kcal}kcal이다.")
}
}
또한 Food 클래스를 상속 받은 Fish 클래스는 생성자 생성시 var를 붙여줄 수 없다.
// 클래스 자체 속성으로 만들어주는 var을 붙이지 말아야 한다.
class Fish(name: String, kcal: String) : Food("수산물", name, kcal) { // 수퍼 클래스의 생성자 호출
fun fishIntroduce() {
println("fish 클래스 메서드 실행")
}
fun salmonIntroduce() {
println("${this.kindValue}의 종류 중 하나인 ${name}는 ${kcal}kcal이다.")
}
}
// main 클래스
fun main(args: Array<String>) {
var food = Food("고기", "한우","800")
var fish = Fish("연어", "500");
food.introduce() // 육류의 중 ..
fish.introduce() // 수산물의 종류 중 ..
fish.fishIntroduce() // fish 클래스 ..
}
main 클래스를 실행하면 다음과 같은 결과가 나온다.
더 나아가
수퍼 클래스의 함수를 서브클래스에서 재구현 할 수 있는 오버라이딩 또한 예시로 살펴보자.
Food 클래스 내부에 eat 함수를 선언하였고 수퍼클래스의 메소드를 오버라이딩 받아 서브 클래스에서 구현할 경우에도 open 선언을 해야한다.
open class Food(var kindValue: String, var name: String, var kcal: String) {
fun introduce() {
println("${kindValue}의 종류 중 하나인 ${name}는/은 ${kcal}kcal이다.")
}
// open 선언 순간 서브클래스에서 오버라이딩 가능하다.
open fun eat(){
println("음식을 먹다.")
}
}
class vegetable(name: String, kcal: String) : Food("풀떼기",name, kcal ) {
override fun eat() { // 수퍼 클래스의 eat 함수 재구현
println("풀떼기를 먹습니다.")
}
}
// main 클래스
fun main(args: Array<String>) {
var vegetable = vegetable("시금치", "100")
vegetable.introduce()
vegetable.eat()
}
Food 클래스에서는 eat 함수가 "음식을 먹다" 이지만 vegetable 클래스의 eat 함수는 "풀떼기를 먹습니다." 로 정의하였다.
introduce는 Food 클래스 내부의 introduce 함수를 실행한 것이며 eat는 vegetable에서 상속받아서 구현한 부분이 실행된 것을 확인 할 수 있다.
08-2. 추상 클래스 / 인터페이스
1) 추상 클래스
추상클래스는 수퍼클래스에서 구현은 되지 않았지만 서브클래스에 필요에 따라 구현이 필요한 함수가 있는 클래스이다.
일부 함수가 구현되지 않았기 때문에 단독으로는 인스턴스를 만들 수 없다.
추상 클래스는 클래스 앞에 abstract 선언은 해야 한다.
코드로 예시를 들어보자.
smartPhone이라는 추상 클래스가 있고 내부에는 CEOName 추상화 함수까지 있다.
이 추상클래스를 samsung 클래스가 상속 받아 구현 해 내는 부분 이다.
abstract class smartPhone {
abstract fun CEOName()
fun price() {
println("너무 비싸..")
}
}
class samsung : smartPhone() {
override fun CEOName() {
println("이재용님 입니다.")
}
}
fun main(args: Array<String>) {
var samsungInfo = samsung()
samsungInfo.CEOName()
samsungInfo.price()
}
smartPhone 클래스는 추상클래스이기 때문에 인스턴스를 생성할 수 없다.
2) 인터페이스
추상화하는 또 다른 방법으로는 인터페이스가 있다.
자바에서의 인터페이스는 추상 클래스와는 다르게 내부 함수 전체가 추상화 형태로 이루어져 있지만 코틀린에서의 인터페이스는 추상 함수와 일반 함수를 모두 가질 수 있다.
(물론 다중 상속은 두 언어 모두 가능)
차이점은 추상클래스는 생성자를 가질 수 있는 반면에 인터페이스는 생성자를 가질 수 없다는 점이다.
또 인터페이스에서 구현부가 잇는 함수는 open 함수, 구현부가 없는 함수는 abstract 함수로 간주하기 때문에 별도의 선언 없어도 서브 클래스에서 구현 및 재정의가 가능하다.
Ipad와 MacBook 이름을 가진 인터페이스를 선언하였다.
Ipad의 hope 함수는 Apple 클래스에서 abstract 함수로 간주하며 (Ipad 내에 구현이 되어 있지 않으므로 껍데기만 있는 형태)
MacBook had 함수는 Apple 클래스에서 open 함수로 간주한다. (오버라이딩 하고 있는 형태)
interface Ipad {
fun hope()
}
interface MacBook {
fun had() {
println("M1 Pro 프로세스가 탑재된 맥북프로를 가지고 있습니다.")
}
}
class Apple : Ipad, MacBook { // 다중 상속
override fun hope() { // abstract 함수로 간주
println("Ipad Pro를 사고 싶습니다.")
}
override fun had() { // 추상함수 : open 함수로 간주
println("그 전에는 Intel 맥북프로를 썼었습니다.")
}
}
fun main(args: Array<String>) {
var apple = Apple()
apple.had()
apple.hope()
}
끝.
참고 자료
https://www.youtube.com/channel/UCVqKQvma-Cr-eQ4hgxETAFQ
'개발 지식 > Kotlin' 카테고리의 다른 글
[Coroutine] Coroutine Basic (0) | 2022.08.23 |
---|---|
[Kotlin] Kotlin 기초 - 05 (문자열) (0) | 2022.08.21 |
[Kotlin] Kotlin 기초 - 04 (스코프 함수) (0) | 2022.07.17 |
[Kotlin] Kotlin 기초 - 03 (스코프 /고차 람다 함수) (0) | 2022.05.16 |
[Kotlin] Kotlin 기초 -01 (0) | 2022.04.24 |
댓글