다형성(polymorphism)
다형성polymorphism이란?
-
객체지향개념에서의 다형성이란 '여러 가지 형태를 가질 수 있는 능력' 을 의미하며 자바에서는
한타입의 참조변수로 여러 가지 타입의 객체를 참조하는것을 말한다 구체적으로 말하면 조상클래스
타입의 참조변수로 자손클래스의 인스턴스를 참조하는것을 말합니다
다형성의 이해
-
다형성이 어떤 식으로 돌아가는지 이해하기 위해 어떻게 레퍼런스를
선언하고 객체를 만드는지 살펴보겠습니다
Dog myDog = new Dog();
1 3 2
1. 래퍼런스 변수를 선언합니다.
Dog myDog = new Dog();
래퍼런스 변수를 위한 공간을 할당하도록 지시 합니다. 레퍼런스 변수의 유형은 한번 정해지면 바뀌지
않습니다. 즉 Cat이나 Wolf 같은 것이 아닌 Dog만을 위한 버튼이 달려있는 리모컨이 된다고 보면 됩니다
2. 객체를 만듭니다.
Dog myDog = new Dog();
JVM 가비지컬렉션 기능이 있는 Heap 에 새로운 Dog 객체를 위한 공간을 할당하도록 지시합니다.
3.객체와 레퍼런스를 연결합니다.
Dog myDog = new Dog();
새로만들어진 Dog객체를 myDog라는 레퍼런스변수 - 참조변수-에 대입합니다.
즉, 리모컨과 그 리모컨으로 제어할 객체를 연결한다고 보면 됩니다.
-
중요한 것은 레퍼런스 유형과 객체 유형이 똑같아야 한다는 점입니다.
-
이 예제에서는 모두 Dog입니다.
myDog --> Dog 객체
(형식은 Dog)
이둘은 같은 유형입니다. 레퍼런스 변수는 Dog 유형으로 선언 했고 객체를 만들때는 new Dog()를 사용했습니다.
-
하지만 다형성을 활용하면 레퍼런스와 객체가 다른 유형이어도 됩니다.
Animal myDog = new Dog();
myDog --> Dog객체
(형식은 Animal)
이둘은 같은 유형이 아닙니다. 레퍼런스 변수는 Animal 유형으로 선언했지만 객체를 만들때는 new Dog()를 사용했습니다.
다형성을 사용하면 레퍼런스 유형을 실제 객체유형의 상위클래스 유형으로 지정할 수 있습니다
이렇게 하면 다형적인 배열을 만드는 것과 같은 일을 할수있습니다
-
반대로 되면 어떨까요?
Dog myDog = new Animal();
mtDog --> Animal 객체
이경우 컴파일 에러가 됩니다 실제 인스턴스인 Animal의 멤버개수 보다 참조변수 myDog가 사용할수있는 맴버개수가 많기 떄문입니다
자손타입의 참조변수로 조상타입의 인스턴스를 참조하는 것은 존재하지 않는 맵버를 사용하게될 가능성이 있으므로 허용되지않습니다
참조변수가 사용할 수 있는 맴버의 개수는 인스턴스의 맴버 개수보다 같거나 적어야 합니다
참조변수의 형변환
-
기본형 변수와 같이 참조변수도 형변환이 가능합니다
단, 서로 상속관계에 있는 클래스에서만 가능.
자손타입 -> 조상타입(Up-casting) 형변환 생략가능
조상타입 -> 자손타입 (Down -casting) 형변환 생략불가
형변환 예제
- class Car{
String color;
int door; - void drive(){
System.out.println("drive");
}
void stop(){
System.out.println("Stop");
}
} - class FireEngine extends Car{
void Water(String s){
System.out.println(s+ " Water");
}
} - class Castingtest{
public static void main(String args[]){ - Car car = null;
FireEngine fe = new FireEngine();
FireEngine fe2 = null; - fe.Water("fe.");
car = fe; //car = (Car)fe; 에서 형변환이 생략된 형태
//car.Water(); //컴파일 에러가 난다 Car타입의 참조변수로는 Water()를 호출할수 없다
fe2 =(FireEngine) car; // 조상타입에서 자손타입으로 downcasting
fe2.Water("fe2.");
}
} -
다형성의 예제
-
-
class Dog extends Animal{
public void makeNoise(){
System.out.println("멍멍~");
} -
public void roam(){
}
}
class Cat extends Animal{
public void makeNoise(){
System.out.println("야옹~");
}
public void roam(){
}
}
class Wolf extends Animal{
public void makeNoise(){
System.out.println("아우우우~~");
}
public void roam(){
}
class Lion extends Animal{
public void makeNoise(){
System.out.println("어흥~"); - }
- public void roam(){
-
}
-
class Animal {
String food;
boolean hunger;
String location;public void makeNoise(){
}
public void eat(){
}
public void sleep(){
}}
-
class Polytest{
-
public static void main(String args[]){
-
- //Animal 유형의 배열, 즉 Animal유형의 객페를 저장할 수 잇는 배열을 선언합니다
- Animal[] animals = new Animal[4];
- //Animal 배열에는 Anmal의 하위클래스에 속하는 모든 객체를 집어놓을수 있습니다
- animals[0]= new Dog();
animals[1]= new Cat();
animals[2]= new Wolf();
animals[3]= new Lion(); - //이부분이 다형성과 관련하여 가장 중요한 부분입니다
- //배열의 모든 원소에 대해 순환문을 돌리면서 Animal클래스에 들어있는 메소드 중
-
//하나를 실행시키면 각객체마다 올바른 메소드를 실행하는 것을 확인 할수 있습니다
for(int i=0 ; i< an.length; i++){
an[i].makeNoise();//i가 0이면 배열의 0번 인덱스 위치에는 Dog객체가 들어 있으므로 Dog의
//makeNoise()메소드를 호출하게 됩니다.
//i가 1이면 Cat의 makeNoise()메소드가 호출됩니다
}
}
}
하나더
-
인자와 리턴유형에 대헤서도 다형성을 적용을 할수있습니다
- class Vet{
public void giveShot(Animal a){
a.makeNoise();
}
} - class PetOwner{
public static void main(String args[]){
Vet v = new Vet();
Dog d = new Dog(); //Vet의 giveShot() 메소드에서는 모든 Animal 을 인자로 받을수 있습니다
Cat c = new Cat(); //인자로 전달된 객체가 Animal 의 하위클래스이기만 하면 제대로 작동합니다
v.giveShot(d); //Dog 의 makeNoise() 가 실행됩니다
v.giveShot(c); //Cat 의 makeNoise() 가 실행됩니다
}
}
History
Last edited on 04/08/2010 16:56 by 아이스
Comments (0)