자식(하위) 클래스에서 부모(상의) 클래스를 재정의하고 싶을때 쓴다.
fun main(){
var family = Family("수도권")
var grandma = Grandma("충북")
var aunt = Aunt("강원")
family.weather()
grandma.weather()
aunt.weather()
}
open class Family(region: String) {
var region = ""
init {
this.region = region
}
open fun weather(){ //오버라이드하고 싶은 메소드에 open 써줘야 상속관계 이용 할 수 있음.
println("${region} : 추워요.")
}
}
class Grandma(region: String) : Family(region){
var hour:Int = 3
init {
this.hour = hour
}
override fun weather() {
super.weather() //상위 클래스의 weather()메소드를 이어 받고 재정의 함.
println("${hour}시간 걸리는 ${region}은 추워요.")
}
}
class Aunt(region: String) : Family(region){
var food:String = "감자"
init {
this.food = food
}
override fun weather() {
super.weather()
println("${food}가 맛있는 ${region}은 추워요.")
}
}
수도권 : 추워요.
충북 : 추워요.
3시간 걸리는 충북은 추워요.
강원 : 추워요.
감자가 맛있는 강원은 추워요.
매개변수의 개수나 자료형을 다르게 하면 같은 이름의 메소드를 여러개 만들 수 있다.
addDouble, addInt와 같이 같은 기능의 이름만 다른 여러 개의 메소드를 만드는 건 나중에 관리하기 힘들다. 같은 클래스 안에 add라고 이름을 똑같이 써도 코틀린 컴파일러가 알아서 자료형이나 매개변수의 개수를 찾아 알맞은 메소드에 적용시킨다.
fun main() {
var calc = Calculator()
var addInts = calc.add(1,2)
var addDoubleS = calc.add(1.1,2.2)
println(addInts)
println(addDoubleS)
}
class Calculator {
fun add(num1: Int, num2: Int) : Int{ // : Int -> 한번 더 자료형을 명시해줌.
return num1 + num2
}
fun add(num1: Double, num2: Double) : Double{ // : Double
return num1 + num2
}
}
3
3.3000000000000003
fun main(){
var calc = Calculator()
var multiTwoNums = calc.multi(2,5)
var multiThreeNums = calc.multi(2,3,4)
println(multiTwoNums)
println(multiThreeNums)
}
class Calculator {
fun multi(num1: Int, num2: Int, num3: Int): Int {
return num1 * num2 * num3
}
fun multi(num1: Int, num2: Int): Int {
return num1 * num2
}
}
10
24
fun main(){
var strObject = AddString()
var addTwoStr = strObject.addstr("내","배")
var addThreeStr = strObject.addstr("내","배","캠")
println(addTwoStr)
println(addThreeStr)
}
class AddString {
fun addstr(str1: String, str2: String): String{
return str1 + str2
}
fun addstr(str1: String, str2: String, str3: String): String{
return str1 + str2 + str3
}
}
내배
내배캠
매개변수: 타입 뿐만 아니라 함수 자체에도 : 타입 명시하는 것 잊지 말기.
a .오버라이딩에서 배웠던 하위 클래스의 재정의는
override fun weather() { super.weather() println("${hour}시간 걸리는 ${region}은 추워요.") } }
상위 클래스의 메소드를 그대로 이어받아서 재정의하는 것이라 새로운 메소드르를 만들 수 없었다. 이 때 필요한 것이 인터페이스인데 다른 파일에 interface 키워드를 넣어 추상 메소드를 만들면 하위 클래스 안에 override interface 추상 메소드를 이용해 새로운 기능의 메소드를 만들 수 있다. 원래는 추상 메소드만을 허용했지만 최근에는 추상 메소드가 아니여도 인터페이스 이용이 가능하다.
interface SummerWeather {
fun summerWeather()
// fun summerWeather() {
// println("여름 날씨")}
}
fun main() {
var aunt = Aunt("강원")
var house = House("수도권")
aunt.summerWeather()
house.summerWeather()
}
open class Family(region: String){ // 1. open으로 상속받게 상위 클래스를 열어주고
var region = ""
init {
this.region = region
}
fun weather(){
println("${region}은 추워요")
}
}
class Aunt(region: String) : Family(region), SummerWeather { // 2. 새로운 하위 클래스를 만들어 매개변수와 자료형을 명시하고 interface 명을 적는다.
override fun summerWeather() { // 3. interface 안에 적었던 추상메소드 명을 오버라이딩하고 추가할 기능을 적는다.
println("여름에 ${region}은 시원해요")
}
}
class House(region: String) : Family(region), SummerWeather {
override fun summerWeather() {
println("${region}은 더워요.")
}
}
여름에 강원은 시원해요
수도권은 더워요.
기능 재정의는 무조건 오버라이딩을 이용한다. interface SummerWeather { } 의 추상메소드( fun summerWeather() )를 가져와서 다시 정의하는 것이니까.