다형성
•
같은 이름의 메소드가 클래스 혹은 객체에 따라 다르게 동작하도록 구현되는 것
•
다형성에는 오버라이딩과 오버로딩이 있습니다.
◦
오버라이딩(Overriding)
▪
슈퍼 클래스의 메소드를 서브 클래스에서 자신의 상황에 맞게 재정의하는 것
◦
오버로딩(Overloadding)
▪
같은 클래스 내부 혹은 상속 관계에 있는 클래스에서 메소드 이름은 같지만 매개변수의 타입과 개수가 다른 메소드들을 여러개 만드는 것
•
그렇다면 이러한 다형성의 개념이 왜 활용되는 것일까요? 예제를 통해 이해해봅시다.
동물을 나타내는 Animal 클래스
package java_0926;
public class Animal{
public void talk(){
System.out.println("동물이 말을 합니다.");
}
}
Java
복사
Animal 클래스를 상속받은 Cat 클래스
package java_0926;
public class Cat extends Animal{
@Override
public void talk(){
System.out.println("야옹");
}
}
Java
복사
Animal 클래스를 상속받은 Dog 클래스
package java_0926;
public class Dog extends Animal {
@Override
public void talk(){
System.out.println("멍멍멍");
}
}
Java
복사
package java_0926;
public class Main {
public static void main(String[] args) {
Animal cat = new Cat();
Animal dog = new Dog();
cat.talk()
dog.talk();
}
}
Java
복사
[출력 결과]
•
위의 예제는 Animal 클래스를 상속받은 Cat 클래스와, Dog 클래스를 나타냅니다.
•
동물은 서로 말하는 방식이 다른 것을 실생활에서 볼 수 있습니다.
•
이는 다형성으로 표현해낼 수 있습니다.
◦
서브 클래스는 슈퍼 클래스로 부터 상속받은 메소드(talk())를 그들의 상황에 맞게 재정의합니다.
◦
이를 우리는 오버라이딩(Overriding)이라고 부릅니다.
◦
따라서, 출력 결과는 “야옹”과 “멍멍멍” 으로 나타나는 것을 볼 수 있습니다.
업캐스팅과 다운 캐스팅
업캐스팅
•
서브 클래스의 객체에 대한 레퍼런스를 슈퍼 클래스 타입으로 변환하는 것
class Person{
...
}
class Student extends Person{
...
}
class Researcher extends Person{
...
}
class Professor extends Researcher{
...
}
Java
복사
Person p = new Student();
Java
복사
•
자바에서 서브 클래스는 슈퍼 클래스의 멤버를 상속 받기 때문에, 서브 클래스 객체는 슈퍼 클래스 멤버를 모두 갖습니다.
•
따라서, 서브 클래스 객체를 슈퍼 클래스가 가리킬 수 있는 것 입니다.
◦
다만, 슈퍼 클래스의 레퍼런스로 서브 클래스의 멤버에 접근하지 못합니다.
◦
슈퍼 클래스의 레퍼런스로는 슈퍼 클래스의 멤버에만 접근할 수 있습니다.
다운캐스팅
•
슈퍼 클래스 타입의 객체를 서브 클래스 타입의 레퍼런스로 가리키는 것
•
다형성 적용으로 잃어버린 특성을 복구 시키기 위해 원래 상태로 되돌리는 것
•
업캐스팅과 달리 명시적으로 타입 변환을 지정해주어야 합니다.
Person p = new Student();
Student s = (Student) p //다운 캐스팅
Java
복사
instanceof 연산자
•
슈퍼 클래스를 상속받은 서브 클래스가 여러개 존재하는 경우, 슈퍼 클래스의 레퍼런스가 가리키는 객체의 진짜 클래스 타입을 구분하는 데에는 어려움이 있습니다.
•
예제를 통해 알아봅시다.
Person p = new Person();
Person p = new Student();
Person p = new Researcher();
Person p = new Professor();
Java
복사
print(p); // Person 타입의 레퍼런스 p가 어떤 타입의 객체를 가리키는지 알 수 없음
public void print(Person person){
//person이 가리키는 객체가 Person 타입이 될 수도,
//Student, Researcher, Professor가 될수도 있다.
}
Java
복사
•
슈퍼 클래스인 Person, 서브 클래스인 Student,Researcher, Professor가 존재합니다.
•
이 때, print() 메소드의 파라미터에는 Person 타입의 객체를 전달받습니다.
◦
print() 메소드가 오직 아는 것은 Person 객체를 상속받은 객체가 업캐스팅 되어 넘어왔거나 혹은 Person 객체가 넘어왔다는 것입니다.
◦
이 때, instanceof 연산자를 이용하면 레퍼런스가 가리키는 객체가 어떤 클래스 타입인지 구분할 수 있습니다.
•
instanceof 연산자 표기법
레퍼런스명 instanceof 클래스타입
public void print(person person){
if(person instanceof Student){
System.out.println("파라미터로 넘어오는 개체의 타입은 Student 타입입니다.")
}
}
Java
복사
•
boolean 타입으로, 레퍼런스가 가리키는 객체가 해당 클래스 타입의 객체이면 true이고 아니면 false로 계산됩니다.
•
instanceof는 클래스에만 적용됩니다.(클래스 타입을 작성하는 부분에 Primitive 타입 X)
•
다음과 같이 instanceof 연산자를 통해, 레퍼런스가 어떤 클래스 타입인지 알 수 있습니다.