다형성과 타입 변환
✒️ 2025-05-15 13:04 내용 수정
하나의 객체가 여러 가지 타입을 가질 수 있는 것
- 하나의 타입으로 다양한 객체를 사용할 수 있다.
- 객체 지향(Object Oriented)#3. 다형성(Polymorphism) 참고.
- 부모 타입으로 타입이 변환되어 저장된 변수는 안에 담긴 객체를 직접 확인하는게 아닌 이상 알기 어렵기 때문에 2가지 방법으로 확인해볼 수 있다.
- 자식 클래스에 오버라이딩 된 메소드를 사용하거나,
instanceof를 사용해서 전달된 객체가 어느 타입인지 확인해볼 수 있다. - 연산자(Operators)의
instanceof참고
- 자식 클래스에 오버라이딩 된 메소드를 사용하거나,
- 완벽한 다형성을 구현하기 위해서는 (상속 + 메소드 오버라이딩 + 클래스 타입 변환) 3개의 개념을 합쳐야 한다.
- 객체가 특정 클래스의 필드가 되면서 하나의 부품처럼 사용될 수 있다.
- 클래스 필드에서 자주 선언해봤던 String 클래스를 떠올려보자.
- 상속 관계의 두 클래스 사이엔 참조 다형성이 있다.
- 상속(Inheritance)에서 자식 클래스가 부모 클래스를 상속 받으면서 다른 멤버도 추가할 수 있다.
- 부모 클래스 타입의 참조 변수로서 자식 클래스의 인스턴스를 참조할 수 있다.
ParentClassName a = new ChildClassName();- 참조 변수가 사용할 수 있는 멤버의 개수가 실제 인스턴스의 멤버 개수보다 적기 때문
- 하지만 자식 클래스 타입의 참조 변수로는 부모 클래스 타입의 인스턴스를 참조할 수 없다.
ChildClassName a = new ParentClassName(); // 오류!- 참조 변수가 사용할 수 있는 멤버의 개수가 실제 인스턴스의 멤버 개수보다 많기 때문
- 형 변환(Casting)에서처럼, 큰 타입에서 작은 타입을 갈 때 데이터 손실이 발생하는 개념으로 이해했다.
- 헷갈린다면 [[상속구조.png]] 구조에서 각 클래스의 멤버 포함 관계를 다시 보자.
타입 변환
1. 자료형의 타입 변환
- 타입을 다른 타입으로 변환하는 것이다.
- 자료형 변환(형 변환(Casting))
- 자동형변환
- 강제형변환 : (데이터타입) 변환할데이터
2. 클래스의 객체 타입 변환
- 서로 상속 관계에 있는 클래스 사이에서만 변환할 수 있다.
- 상속(Inheritance)
- 자료형 변환처럼 자동형변환, 강제형변환이 있다.
- 하나의 클래스는 1개의 타입을 가지지만, 상속을 하면 상위 클래스의 타입을 가질 수 있다.
- 객체가 해당 타입을 가지고 있어야만 타입 변환이 가능하다.
- 1차 상속 관계가 아니더라도 가능하다. (조상 클래스의 필드를 쓸 수 있다.)
- 타입 변환은 변환한다고 객체가 바뀌는 게 아니라, 객체는 보존되고, 사용만 부모 객체처럼 사용할 수 있다.
- 부모 타입으로 변환한 객체는 더 이상 자신의 클래스에 추가한 필드를 사용할 수 없고, 부모 클래스에 선언된 필드만 사용할 수 있다.
- 부모 클래스 입장에선 자식 클래스가 뭘 가지고 있고 뭘 할 수 있는지 알 수 없다.
- 단, 부모 클래스 메소드를 오버라이딩한 경우 자식 클래스에 오버라이딩 된 메소드를 먼저 호출한다
1) 자동 형변환
- 상속관계에 있는 자식 클래스의 객체를 부모 타입의 객체로 변환할 때 자동 형변환이 일어난다.
- 타입 변환을 위해 참조 변수가 실제로 참조하는 인스턴스의 타입을 확인하기 위해 연산자(Operators) 중
instanceof연산자를 사용한다.A instanceof B로, 참조 타입이 같으면 true, 다르면 false를 반환
ParentClassName a = new ParentClassName();
ChildClassName a = new ChildClassName();
ParentClassName a = new ChildClassName();
ChildClassName a = new ParentClassName(); // 오류!
2) 클래스의 강제형변환
- 자식 타입에서 부모 타입으로 타입 변환을 한 이후 다시 자식 클래스의 멤버에게 접근하고 싶을 때 접근을 할 수 있는 방법
- 1회성으로 타입 변환이 필요할 때
(자식클래스명)변수명.메소드명();
- 자식 클래스의 멤버에 접근이 여러 번 필요한 경우
자식클래스이름 객체이름 = (자식클래스이름)부모타입객체;
// 부모와 자식 클래스 지정
class ParentClassName {}
class ChildClassName extends ParentClassName {}
// 인스턴스 생성
ParentClassName a = new ParentClassName();
ChildClassName b = new ChildClassName(); // child class는 부모의 타입도 가지고 있다
// 부모 클래스 변수에 자식 클래스를 배정
a = b; // 자동형변환 (자식클래스 -> 부모클래스)
// a는 b의 기능이나 속성을 사용할 수 없다
// 자식 클래스 변수에 부모 클래스를 강제형변환 후 배정
b = (ChildClassName)a; // 강제형변환 (부모클래스 -> 자식클래스)