꿈틀꿈틀 개발일기

20231212 / 업 캐스팅과 다운 캐스팅

by jeongminy

■ 자료형 변환

- 숫자자료형끼리 : .toInt() | .toDouble()
- 문자형->정수형 : Integer.parseInt(바꾸고싶은것)
- 문자형->실수형(소수) : .toDouble()

더보기
var num1 = 20
    var num2 = 30.2

    var num3 = num2.toInt()
    var num4 = num1.toDouble()

    var strNum5 = "10"
    var strNum6 = "10.21"

    var num5 = Integer.parseInt(strNum5)
    var num6 = strNum6.toDouble()

    println("num3: $num3")
    println("num4: $num4")
    println("num5: $num5")
    println("num6: $num6")
위 코드의 출력 이미지

 

 


■ 객체 자료형간의 변환 (상속관계에서 가능)

업 캐스팅
자식(서브,하위)클래스부모(슈퍼, 상위)클래스 타입으로 자동으로 형변환(타입변환) 하는 것 (다형성)
- 객체 내 모든 변수, 메소드에 접근할 수 없고 상위클래스의 변수, 메소드에만 접근 가능
- 단, 하위클래스가 상위클래스의 메소드를 오버라이딩한 경우 하위클래스의 메소드를 호출

"사과"와 "바나나"는 모두 "과일"입니다. 따라서 "사과"와 "바나나"는 "과일"이라는 큰 틀에서 묶을 수 있습니다.
클래스에서도 마찬가지입니다. 부모 클래스는 자식 클래스를 포함합니다.
따라서, 부모 클래스는 자식 클래스보다 큰 틀이라고 할 수 있습니다.
"큰 틀"의 클래스 타입의 변수에는 "작은 틀"의 클래스 타입의 인스턴스를 저장할 수 있습니다. 이것이 업캐스팅입니다.

ex) 사과는 과일이다 -> 말 됨!! -> 자동으로 형변환
      과일은 사과다 -> 말 안됨!!!

더보기
class Animal {
    fun eat() {
        println("밥을 먹습니다.")
    }
}
class Dog : Animal() {
    fun bark() {
        println("멍멍!")
    }
}
fun main(args: Array<String>) {
    val animal: Animal = Dog()

    animal.eat() // 밥을 먹습니다.

    // Dog의 bark() 메서드는 Animal의 eat() 메서드를 상속받습니다.
    // 따라서 animal 변수에 Dog 인스턴스를 할당하면 bark() 메서드를 사용할 수 있습니다.
    animal.bark() // 멍멍!
}

Animal 클래스가 Dog 클래스의 부모 클래스입니다.
따라서, Animal 클래스는 Dog 클래스보다 큰 틀이라고 할 수 있습니다.

위 코드에서는 Animal 타입의 변수 animal에 Dog 타입의 인스턴스를 할당합니다.
animal 변수는 Dog 타입의 인스턴스를 저장할 수 있는 이유는 Dog 클래스가 Animal 클래스를 상속받기 때문입니다.

업캐스팅을 수행하면, Dog 클래스 타입의 인스턴스의 멤버는 Animal 클래스 타입의 변수에서 사용할 수 있습니다.

예를 들어, 위 코드에서 animal.eat()을 호출하면 Dog 클래스의 eat() 메서드가 호출됩니다.
이는 Dog 클래스의 eat() 메서드가 Animal 클래스의 eat() 메서드를 상속받기 때문입니다.

 


■ 다운 캐스팅
- 업 캐스팅 된 객체를 강제 형변환으로 본래의 자료형태로 되돌려 놓는 것
( 전제조건 : 업캐스팅된 객체만 다운캐스팅이 가능하다! )
- 업 캐스팅 된 객체가 아니더라도 문법적인 오류는 없지만, 실행 후 compile시 문제가 발생한다!!

"사과"는 "과일"입니다. 하지만, "사과"는 "과일" 중에서도 "사과"라는 작은 틀에 속합니다. 따라서, "사과"는 "사과"라는 틀에 속하는 멤버만 사용할 수 있습니다.
클래스에서도 마찬가지입니다. 자식 클래스는 부모 클래스의 모든 멤버를 사용할 수 있지만, 부모 클래스는 자식 클래스의 일부 멤버만 사용할 수 있습니다.
다운캐스팅은 "작은 틀"의 클래스 타입의 변수를 "큰 틀"의 클래스 타입의 변수로 변환하는 것을 말합니다.

다운 캐스팅의 사용
- 상위 클래스 타입의 객체가 실제로 하위 클래스 타입의 객체인지 확인해야 할 때
- 상위 클래스 타입의 객체에서 하위 클래스 타입의 멤버에 접근해야 할 때

다운 캐스팅은 사용하기 까다롭고 오류를 유발하기 쉽기 때문에 자주 사용되지 않습니다.

더보기

예를 들어, 다음과 같은 클래스 계층 구조가 있다고 가정해 보겠습니다.

class Animal {
    fun eat() {
        println("밥을 먹습니다.")
    }
}

class Dog : Animal() {
    fun bark() {
        println("멍멍!")
    }
}

Dog 클래스는 Animal 클래스의 자식 클래스입니다. 따라서, Dog 클래스는 Animal 클래스의 모든 멤버를 사용할 수 있습니다.

하지만, Animal 클래스는 Dog 클래스의 bark() 메서드를 사용할 수 없습니다. 이는 Animal 클래스가 Dog 클래스의 bark() 메서드를 상속받지 않았기 때문입니다.

다운캐스팅은 "작은 틀"의 클래스 타입의 변수를 "큰 틀"의 클래스 타입의 변수로 변환하는 것을 말합니다.

예를 들어, 다음과 같은 코드를 살펴보겠습니다.

fun main(args: Array<String>) {
    val dog: Dog = Dog()

    // dog 변수는 Dog 타입입니다.

    // dog 변수를 Animal 타입으로 다운캐스팅합니다.
    val animal: Animal = dog as Animal

    // animal 변수는 Animal 타입입니다.

    animal.eat() // 밥을 먹습니다.
}

위 코드에서는 Dog 타입의 변수 dog를 Animal 타입의 변수 animal로 다운캐스팅합니다. animal 변수는 Dog 타입의 인스턴스를 저장할 수 있기 때문에 다운캐스팅이 가능합니다.

다운캐스팅을 수행하면, animal 변수는 Dog 클래스의 모든 멤버에 접근할 수 있습니다.

예를 들어, 위 코드에서 animal.eat()을 호출하면 Dog 클래스의 eat() 메서드가 호출됩니다. 이는 dog 변수가 Dog 타입의 인스턴스를 저장하고 있기 때문입니다.

초등학생에게 설명하는 수준으로 클래스의 다운캐스팅에 대해서 설명해 보았습니다. 도움이 되었기를 바랍니다.

다음과 같은 비유를 사용하면 이해하기가 더 쉬울 수도 있습니다.

"사과"는 "과일" 중에서도 "사과"라는 작은 틀에 속한다고 했습니다. 따라서, "사과"는 "사과"라는 틀에 속하는 멤버만 사용할 수 있습니다.

"사과"를 "과일"로 다운캐스팅하면, "사과"는 "과일"이라는 큰 틀에 속하게 됩니다. 따라서, "사과"는 "과일"이라는 틀에 속하는 멤버도 사용할 수 있게 됩니다.

예를 들어, "사과"는 "빨간색"이라는 멤버를 가지고 있습니다. 하지만, "과일"은 "빨간색"이라는 멤버를 가지고 있지 않습니다.

"사과"를 "과일"로 다운캐스팅하면, "사과"는 "빨간색"이라는 멤버를 사용할 수 있게 됩니다.

이렇게 생각하면, 클래스의 다운캐스팅이 어떻게 작동하는지 이해하기가 더 쉬울 것입니다.

블로그의 정보

꿈틀꿈틀 개발일기

jeongminy

활동하기