다형성 이해하기
- 메서드 오버 라이딩
- 업 캐스팅
- 다형성이란?
- 다운 캐스팅 (instanceof)
메서드 오버 라이딩
부모 클래스에서 정의된 메서드 중에서 자식 클래스에서 기능이 맞지 않거나 추가적인 기능이 필요한 경우 메서드를 재정의 하는 것을 의미합니다. 단 오버 로딩(Overloading)과 다르게 입력받는 매개변수가 동일하여야 합니다.
public class Character{
String name;
public void attack(){
System.out.println("주먹을 휘둘렀습니다.");
}
}
public class Warrior extends Character{
//오버라이딩
public void attack(){
System.out.println("검을 휘둘렀습니다.");
}
public void defence(){
System.out.println("공격을 막았습니다.");
}
}
public class Wizard extends Character{
public void attack(){
System.out.println("지팡이를 휘둘렀습니다.");
}
public void magic(){
System.out.println("파이어 볼을 사용하였습니다.");
}
}
위의 예시는 Character라는 부모 클래스와 상속을 받은 Warrior라는 자식 클래스가 있습니다. 두 클래스 모드 attack이라는 함수를 가지고 있습니다. 자식 클래스에서는 attack을 호출하면 주먹이 아닌 검을 휘두르게 하고 싶은 경우 위의 예시처럼 선언을 하게 되고 이를 오버 라이딩이라고 합니다.
업 캐스팅
업 캐스팅은 상속에서 자주 쓰이는 묵시적 형 변환이라고 생각하시면 됩니다. 변수를 선언할 때 클래스 형을 부모 클래스 즉 상위 클래스로 선언을 하지만 인스턴스 생성은 자식 클래스 즉 하위 클래스로 생성할 수 있습니다.
public class GameMake{
public static void main(String[] args){
Character firstCharacter = new Warrior();
Warrior secondCharacter = new Character(); //불가능
}
}
위와 같이 Warrior 클래스의 인스턴스를 만드는데 클래스 선언은 Character 클래스로 할 수 있습니다. 다만 반대의 경우는 불가능합니다. 비유를 한다면 모든 전사는 캐릭터이지만 모든 캐릭터가 전사는 아니기 때문에 상위 클래스로만 선언이 가능합니다.
public class GameMake{
public static void main(String[] args){
Character firstCharacter = new Warrior();
Character secondCharacter = new Character();
firstCharacter.attack();
secondCharacter.attack();
/*출력
검을 휘둘렀습니다.
주먹을 휘둘렀습니다.
*/
}
}
선언된 클래스는 Character이지만 인스턴스는 다르기 때문에 인스턴스에 맞는 메서드가 호출되어 firstCharacter의 경우 검을 휘둘렀다는 문구가 나오게 되고 secondCharacter의 경우 주먹을 휘둘렀다는 문구가 나오게 됩니다.
다형성이란?
자바 코딩을 할 때 하나의 코드가 여러 가지 자료형으로 구현되어 실행되는 것을 다형성이라고 합니다.
public class GameMake{
public static void main(String[] args){
Character firstCharacter = new Warrior();
Character secondCharacter = new Character();
GameMake gameMake = new GameMake();
gameMake.characterAttack(firstCharacter);
gameMake.characterAttack(secondCharacter);
}
public void characterAttack(Character character){
character.attack();
}
}
위의 예시는 하나의 클래스를 상속받은 여러 클래스가 있는 경우 각 클래스마다 같은 이름의 서로 다른 메서드 즉 오버 라이딩된 메서드를 인스턴스에 따라 구현이 다르게 되는 기능을 보였습니다. characterAttack이라는 메서드에 입력받는 변수는 Character클래스로 받게 됩니다. 업 캐스팅에서도 말씀드렸듯 선언한 클래스는 같지만 인스턴스가 다르기 때문에 characterAttack메서드를 실행 시 인스턴스에 맞는 attack메서드를 불러오게 됩니다. 이러한 기능을 다형성이라고 합니다.
다운 캐스팅 (instanceof)
다운 캐스팅은 업 캐스팅된 변수에서 사용할 수 없는 자식 클래스 즉 하위 클래스에만 존재하는 변수 혹은 메서드를 사용하기 위해 클래스 형을 하위 클래스 형으로 변형하는 것입니다. 단순한 형 변환과 비슷합니다.
public class Character{
String name;
public void attack(){
System.out.println("주먹을 휘둘렀습니다.");
}
}
public class Warrior extends Character{
//오버라이딩
public void attack(){
System.out.println("검을 휘둘렀습니다.");
}
public void defence(){
System.out.println("공격을 막았습니다.");
}
}
public class Wizard extends Character{
public void attack(){
System.out.println("지팡이를 휘둘렀습니다.");
}
public void magic(){
System.out.println("파이어 볼을 사용하였습니다.");
}
}
부모 클래스에는 defence메서드와 magic메서드는 존재하지 않습니다. 따라서 Warrior와 Wizard를 Character클래스로 선언 시 defence메서드와 magic메서드를 사용할 수 없습니다. 이 두 함수를 사용하기 위해서 Character로 선언된 변수를 형 변환하도록 하겠습니다.
public class GameMake{
public static void main(String[] args){
Character firstCharacter = new Warrior();
Character secondCharacter = new Character();
Character thirdCharacter = new Wizard();
Warrior warrior = (Warrior)firstCharacter;
warrior.defence(); //불가능
}
}
위의 경우처럼 기존의 형 변환처럼 다운 캐스팅을 하고 나서 메서드를 불러올 수 있습니다. 하지만 이런 경우 업 캐스팅을 한 이유가 없습니다. 그렇기 때문에 사용하는 예약어 instanceof가 있습니다.
public class GameMake{
public static void main(String[] args){
GameMake gameMake = new GameMake();
Character firstCharacter = new Warrior();
Character secondCharacter = new Character();
Character thirdCharacter = new Wizard();
gameMake.skill(firstCharacter);
gameMake.skill(secondCharacter);
gameMake.skill(thirdCharacter);
/*출력
공격을 막았습니다.
기술이 없습니다.
파이어 볼을 사용하였습니다.
*/
}
public void skill(Character character){
if(character instanceof Warrior){
Warrior warrior = (Warrior)character;
warrior.defence();
}
else if (character instanceof Wizard){
Wizard wizard = (Wizard)character;
wizard.magic();
}
else{
System.out.println("기술이 없습니다.");
}
}
}
skill메서드에서 instanceof를 통하여 character가 어떠한 인스턴스를 가지는지 확인을 하여 인스턴스에 맞는 기술을 사용할 수 있도록 코딩을 해주었습니다. 위와 같이 사용을 하면 메서드가 작동하는 동안에만 다운 캐스팅이 진행되므로 메인 함수에서는 업 캐스팅 상태를 유지할 수 있습니다.