다형성이란 같은 타입이지만 실행 결과가 다양한 객체를 이용할 수 있는 성질을 말한다.
다형성을 통하면 하나의 타입에 여러 객체를 대입함으로써 다양한 기능을 이용할 수 있다.
자바에서는 다형성을 위해 부모 타입에 모든 자식 객체가 대입될 수 있게 한다.
public class PhoneTest{
Phone phone1 = new IPhone();
Phone phone2 = new SPhone(); //자식 객체가 부모의 타입인 Phone에 대입되었다.
}
자동 타입 변환은 프로그램 실행 도중에 자동적으로 타입 변환이 일어나는 것을 말한다.
자식은 부모의 특징과 기능을 상속받기 때문에 부모와 동일하게 취급될 수 있다는 것이 바로 자동 타입 변환의 개념이다.
public class Animal{
}
public class Cat extends Animal{
}
Cat cat = new Cat();
Animal animal1 = cat; //cat객체를 생성하고 animal1변수에 대입하면 자동타입변환된다.
이 경우 cat 변수와 animal1 변수는 타입만 다를 뿐이지, 동일한 cat 객체를 참조하고 있다.
이러한 타입 변환은 바로 위의 부모가 아니더라도 상속 계층에서 상위 타입이라면 일어날 수 있다.
만약 부모 타입으로의 자동 타입 변환을 했다면, 부모 클래스에 선언된 필드와 메서드에만 접근 가능하다.
즉 변수는 자식 객체를 참조하긴 하지만, 변수를 통해 자식 객체의 필드나 메서드에는 접근할 수 없다.
예외적으로 부모 타입으로 자동 타입 변환한 변수가 자식 객체의 메서드에 접근할 수 있는 경우가 있다.
바로 자식 클래스에서 오버 라이딩 했을 경우이다.
자식 클래스에서 오버라이딩 되었다면, 자식 클래스의 메서드가 대신 호출된다.
class Animal{
public void walk(){
System.out.println("동물이 지나갑니다.");
}
}
class Cat extends Animal{
public void walk(){ // Animal 클래스의 walk() 메서드를 오버라이딩했다.
System.out.println("고양이가 지나갑니다.");
}
}
public class Test {
public static void main(String[] args) {
Cat cat = new Cat(); //Cat 클래스로부터 cat 객체 생성
Animal animal = cat; //animal변수에 cat객체 대입->animal변수는 cat객체 참조
//자동 타입 변환의 특징 상 animal 변수는 Animal의 멤버에만 접근가능
animal.walk();
}
}
자동 타입 변환의 특징 상 animal 변수는 Animal 클래스의 멤버에만 접근 가능하므로,
animal.walk()를 실행하면 "동물이 지나갑니다" 를 출력해야한다.
하지만 자식 클래스인 Cat 클래스에서 walk 메서드를 재정의, 오버라이딩 했기 때문에 결과는 다음과 같다.
자동 타입 변환은 메서드를 호출할 때에도 많이 발생한다.
class User{
public void use(Phone phone){
phone.turnOn();
}
}
public class Test {
public static void main(String[] args) {
User user = new User();
iPhone iphone = new iPhone();
sPhone sphone = new sPhone();
User.use(iphone); //메서드의 매개변수로 자식객체가 들어와 자동타입변환
User.use(sphone);
//또는
User.use(new Phone());
User.use(new iPhone());
User.use(new sPhone());
}
}
이처럼 매개값의 자동타입변환과 메서드 오버라이딩을 통해 매개변수의 다형성을 구현할 수 있다.
앞에서 자식 타입을 부모 타입으로 자동타입변환을 하게 되면 자식 클래스의 멤버를 사용할 수 없다는 것을 배웠다.
만약에 꼭 자식 클래스의 필드나 메서드를 사용해야 한다면, 강제 타입 변환을 이용하면 된다.
class Parent {
String field1;
void method1(){}
void method2(){}
}
class Child extends Parent{
String field2;
void method3(){}
}
public class Test{
public static void main(String[] args){
Parent parent = new Child(); // 자동타입변환(자식타입 -> 부모타입)
parent.field1 = "data"
parent.method1();
parent.method2();
/*
parent.field2="data"
parent.method3(); 자동타입변환 시에 자식클래스의 멤버x
*/
Child child = (Child) parent; //강제타입변환(부모타입 -> 자식타입). child변수로
child.field2="data"
child.method3(); //자식 클래스 멤버 접근 가능
}
}
자식 클래스의 멤버를 이용하기 위해 부모타입에서 자식타입으로 다시 강제 타입 변환하는 방법을 확인했다.
주의사항으로는 자식 타입이 부모 타입으로 변환되어있는 상태에서만 강제 타입 변환을 할 수 있다.
만약 부모 타입의 변수가 부모 객체를 참조할 경우에는 자식 타입으로 변환하지 못한다.
이 경우를 피하기 위해서는 부모 변수가 참조하는 객체가 자식 객체인지, 부모 객체인지 확인해보아야 한다.
instanceof 연산자를 이용하면 확인할 수 있다.
boolean 변수 = 객체 instanceof 타입
우항의 타입으로 객체가 생성되었다면 true를 반환
public void method(Parent parent){
if (parent instanceof Child){ //Child타입으로 parent가 참조하는 객체 생성된것이면 true
//true이면 자동타입변환되었다는 것을 의미
Child child = (Child) parent; //실행 : true이면 강제타입변환
}
}
'Dev > Java' 카테고리의 다른 글
[Java] 인터페이스 (0) | 2022.08.06 |
---|---|
[Java] 추상클래스 (0) | 2022.07.27 |
[Java] 접근 제한자 / 싱글톤 패턴 / Getter , Setter (0) | 2022.07.19 |
[Java] final 키워드 (0) | 2022.07.16 |
[Java] 메서드 오버라이딩 (0) | 2022.07.11 |
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!