천천히 빛나는
Java 기초 : 다형성 (Polymorphism) 본문
다형성 (Polymorphism)
class A{
public String x(){return "x";}
}
class B extends A{
public String y(){return "y";}
}
public class PolymorphismDemo1 {
public static void main(String[] args) {
A obj = new B();
obj.x();
obj.y(); // 오류 발생
}
}
부모 클래스 A, 자식 클래스 B가 있을 때 클래스 B의 객체를 A에 담을 수가 있다. 하지만 클래스 B의 메소드 y를 실행할 수는 없다. 클래스 B의 데이터 형을 클래스 A로 하면 클래스 B는 마치 클래스 A인것처럼 동작하게 된다.
class A{
public String x(){return "A.x";}
}
class B extends A{
public String x(){return "B.x";}
public String y(){return "y";}
}
public class PolymorphismDemo1 {
public static void main(String[] args) {
A obj = new B();
System.out.println(obj.x());
}
}
하지만 위 코드에서는 오버라이딩된 함수의 결과값이 출력된다. 즉 B.x가 출력되는 것이다.
- 새롭게 추가한 함수는 실행 불가
- 상위 클래스의 함수를 오버라이딩 했다면 그 값이 출력
class A{
public String x(){return "A.x";}
}
class B extends A{
public String x(){return "B.x";}
public String y(){return "y";}
}
class B2 extends A{
public String x(){return "B2.x";}
}
public class PolymorphismDemo1 {
public static void main(String[] args) {
A obj = new B();
A obj2 = new B2();
System.out.println(obj.x());
System.out.println(obj2.x());
}
}
그렇다면 위 코드는 어떤 값이 출력될까? 정답은 B.x와 B2.x이다.
데이터 타입이 부모 클래스이기 때문에 부모클래스에서 정의한 함수만 호출할 수가 있다. 하지만 하위 클래스에서 오버라이딩 했다면 그 함수가 출력되게 된다. 하위 클래스에서 추가한 메소드들은 호출할 수 없다.
abstract class Calculator{
int left, right;
public void setOprands(int left, int right){
this.left = left;
this.right = right;
}
int _sum() {
return this.left + this.right;
}
public abstract void sum();
public abstract void avg();
public void run(){
sum();
avg();
}
}
class CalculatorDecoPlus extends Calculator {
public void sum(){
System.out.println("+ sum :"+_sum());
}
public void avg(){
System.out.println("+ avg :"+(this.left+this.right)/2);
}
}
class CalculatorDecoMinus extends Calculator {
public void sum(){
System.out.println("- sum :"+_sum());
}
public void avg(){
System.out.println("- avg :"+(this.left+this.right)/2);
}
}
public class CalculatorDemo {
public static void main(String[] args) {
Calculator c1 = new CalculatorDecoPlus();
c1.setOprands(10, 20);
c1.run();
Calculator c2 = new CalculatorDecoMinus();
c2.setOprands(10, 20);
c2.run();
}
}
CalculatorDecoPlus c1 = new CalculatorDecoPlus();가 아니라 Calculator c1 = new CalculatorDecoPlus();라고 되어있는 부분을 주목하면 된다. c1.run()과 c2.run()은 다른 값을 출력하게 된다.
인터페이스와 다형성
interface I{}
class C implements I{}
public class PolymorphismDemo2 {
public static void main(String[] args) {
I obj = new C();
}
}
특정한 인터페이스를 구현하고 있는 클래스가 있을 때 이 클래스의 데이터 타입으로 인터페이스를 지정할 수 있다.
interface I2{
public String A();
}
interface I3{
public String B();
}
class D implements I2, I3{
public String A(){
return "A";
}
public String B(){
return "B";
}
}
public class PolymorphismDemo3 {
public static void main(String[] args) {
D obj = new D();
I2 objI2 = new D();
I3 objI3 = new D();
obj.A();
obj.B();
objI2.A();
//objI2.B();
//objI3.A();
objI3.B();
}
}
인터페이스 I2는 메소드 A만을 정의하고 있고 I2를 데이터 타입으로 하는 인스턴스는 마치 메소드 A만을 가지고 있는 것처럼 동작한다.
클래스 형변환
public class Rabbit extends Animal {
public Rabbit() {
super();
}
@Override
public void eat() {
System.out.println("토끼가 풀을 뜯어 먹습니다");
}
public void jump() {
System.out.println("토끼가 깡총깡총 뜁니다");
}
}
Animal을 상속받는 Rabbit이 있다.
Animal a1 = new Rabbit();
a1.jump(); // 오류남
((Rabbit)a1).jump(); // 클래스 형변환 -> 런타임 오류
a1으로 jump()를 실행하려면 Rabbit으로 다운캐스팅을 해줘야 한다. 하지만 (Rabbit)과 같이 작성해줘도 런타임 오류가 난다.
if(a1 instanceof Rabbit) {
((Rabbit)a1).jump();
}
이와 같이 instance of을 통해 해당 타입이 맞는지 확인하고 다운캐스팅이 가능하다.
'JAVA > JAVA' 카테고리의 다른 글
Java 기초 : Collections Framework (0) | 2024.01.23 |
---|---|
Java 기초 : 인터페이스 (interface) (0) | 2024.01.17 |
Java 기초 : 접근 제어자 & Abstract & final (0) | 2024.01.16 |
Java 기초 : API와 API 문서 보는 법 (0) | 2024.01.16 |
Java 기초 : 클래스 패스와 패키지 (0) | 2024.01.15 |