본문 바로가기
국비 교육/백엔드(Java, Spring)

[자바] 다형성(polymorphism) 예제 - 도형 프로그램 설계

by 육츠 2024. 1. 29.
Contents 접기

다형성

하나의 객체가 여러 가지 타입을 가질 수 있는 것

Parents (세 도형의 공통점)

점(MyPoint)
 - x : int   //private
 - y : int
 + toString() : String // public  
 + calcArea(): double
생성자, 세터게터 필요

상속받으면 반드시 면적을 계산 ==> abstract로

Child

원(MyCircle) extends MyPoint 삼각형(MyTriangle)  extends MyPoint 사각형(MyRectangle)  extends MyPoint
 - radius : double  // 원에만
 + toString() : String
 + calcArea() : double
 - width : double
 - height : double
 + toString() : String
 + calcArea() : double
 - width : double
 - height : double
 + toString() : String
 + calcArea() : double

 

MyPoint

package shape.vo;

public abstract class MyPoint {
	private int x;
	private int y;
	
	
	public MyPoint() {
		super();
	}


	public MyPoint(int x, int y) {
		super();
		this.x = x;
		this.y = y;
	}


	public int getX() {
		return x;
	}


	public int getY() {
		return y;
	}


	public void setX(int x) {
		this.x = x;
	}


	public void setY(int y) {
		this.y = y;
	}
	
	// 일반 메소드 = 면적을 구하는 메소드
	public abstract double calcArea();


	@Override
	public String toString() {
		return "x=" + x + ", y=" + y ;
	}


}
코드 의미
public abstract double calcArea(); 일반 메소드 = 면적을 구하는 메소드

 

MyCircle

package shape.vo;

public class MyCircle extends MyPoint {
	private double radius;
	
	
	// 생성자
	public MyCircle() {
		super();
	}

	public MyCircle(double radius) {
		super();
		this.radius = radius;
	}


	public double getRadius() {
		return radius;
	}

	public void setRadius(double radius) {
		this.radius = radius;
	}

	@Override
	public double calcArea() {
		return this.radius * this.radius * Math.PI; 
	} 	// 원의 면적

	@Override
	public String toString() {
		return super.toString()+   // 부모의 toString()
				", radius = " + radius + ", area = " + calcArea();
	}
	
	

}

 

 

main (하나씩 만들면서 확인해 보기)

package shape.main;

import shape.vo.MyCircle;

public class ShapeMain {
	public static void main(String[] args) {
		//Circle 만들고 확인
		MyCircle c = new MyCircle(5);
		System.out.println(c);
		
		c.setX(4);
		c.setY(3);
		System.out.println(c);
		
	}

}

x=0, y=0, radius = 5.0, area = 78.53981633974483
x=4, y=3, radius = 5.0, area = 78.53981633974483

 

MyRectangle

package shape.vo;

public class MyRectangle extends MyPoint {
	private double width;
	private double height;
	

	public MyRectangle() {
		super();
	}

	public MyRectangle(double width, double height) {
		super();
		this.width = width;
		this.height = height;
	}


	public double getWidth() {
		return width;
	}

	public double getHeight() {
		return height;
	}

	public void setWidth(double width) {
		this.width = width;
	}

	public void setHeight(double height) {
		this.height = height;
	}

	@Override
	public double calcArea() {
		return width * height;
	}

	@Override
	public String toString() {
		return super.toString() + ", width = " + width + ", height = " + height + ", area = " + calcArea();
		
	}
	
	

}

 

MyTriangle

package shape.vo;

public class MyTriangle extends MyPoint {
	
	private double width;
	private double height;
	
	public MyTriangle() {
		super();
	}

	public MyTriangle(double width, double height) {
		super();
		this.width = width;
		this.height = height;
	}


	public double getWidth() {
		return width;
	}

	public double getHeight() {
		return height;
	}

	public void setWidth(double width) {
		this.width = width;
	}

	public void setHeight(double height) {
		this.height = height;
	}

	@Override
	public double calcArea() {
		return width * height * 0.5;
	}

	@Override
	public String toString() {
		return super.toString() +", width = " +  width + ", height = " + height + ", area = " + calcArea() ;
	}
	
	

}

 

다형성 예시

MyPoint 에 임시 메소드(temp)를 넣음

	// 다형성 테스트
	// 임시메소드
	public void temp() {
		System.out.println("포인트 클래스입니다~");
	}

MyCircle

	// 다형성 테스트
	// 임시메소드
	@Override
	public void temp() {
		System.out.println("원 클래스입니다~");
	}

Main

하게 되면 원 클래스의  temp 안에 속한 출력문이 나온다.

package shape.main;

import shape.vo.MyCircle;
import shape.vo.MyPoint;
import shape.vo.MyRectangle;
import shape.vo.MyTriangle;

public class ShapeMain {
	public static void main(String[] args) {
    	MyPoint p = new MyCircle(); 
        p.temp();
        System.out.println(p);

 

다형성 특징

1. 부모의 레퍼런스 변수가 자식 객체의 위치값을 갖도록 한다.

- MyPoint 는 객체를 생성할 수 없다.
-> ? abstract 이니까 p =  MyPoint 라고 생각하지만 사실은 MyCircle 인 것 = 다형성

- 오버라이드와는 무슨 연관?
각자 같은 이름의 메소드가 존재
-> 포인트는 C 안에 MyPoint Temp를 가리킨다 생각하지만 사실은 MyCircle 의 temp를 가리키는 것이다.

System.out.println(p);  = p.toString()과 같다  -> 원에 대한 출력문이 나오게 된다.

오버라이드를 하지 않은 클래스에서 temp를 부른다면?

p = new MyRectangle();     
p.temp();  
System.out.println(p);

포인트 클래스입니다~
x=0, y=0, width = 0.0, height = 0.0, area = 0.0

MyPoint 클래스에서 만들어진 temp 메소드 출력문이 나오게 된다.
=> 상속이 되어야만 다형성 가능하다.

 

2. 캐스팅

타입 변환 = 형 변환

		MyPoint p = new MyCircle();   // 부모가 자식객체를   
		// 다운캐스팅 (부모타입을 자식으로 변환)

		MyCircle tt = new MyCircle();
		// MyPoint 로 업캐스팅(자식을 부모로 변환)
		MyPoint tmp = ((MyPoint)tt);  
		// MyCircle -> MyPoint로 
		((MyPoint)p).temp(); // p를 캐스팅 후에 불러옴.
업 캐스팅 다운 캐스팅
MyPoint tmp = ((MyPoint)tt);  MyPoint p = new MyCircle(); 
자식  클래스가 부모 클래스 타입으로 캐스팅 되는 것. 부모 클래스가 자식 클래스 타입으로 캐스팅 되는 것.

 

 instanceof 연산자

실제 가리키는 타입이 맞는지 확인하는 연산
형태 : 변수 instanceof 타입

		Object obj = new Object();
		
        System.out.println(p instanceof MyPoint); // true  // x
		// 실제 가리키는 타입이 맞는지 확인하는 연산자
		System.out.println(p instanceof MyCircle); // true  // ** 많이 사용
		// 선언된 것도 맞지만 실제로 가리키는 것도 같이 확인 한다.
		System.out.println(tt instanceof MyCircle); // true  // x
		// 상속관계가 맞으면 무조건 true 
		
		// System.out.println(tt instanceof MyRectangle); // 오류
		// 상속관계가 아니닌ㄲㅏ!
		
		System.out.println(obj instanceof MyPoint); // false
		// 부모는 자식을 .. 확인하지는 못 한다.
		// 잘 안씀 오직 예제
코드 의미
1) System.out.println(p instanceof MyPoint); true
2) System.out.println(p instanceof MyCircle);  true
선언된 것도 맞지만 실제로 가리키는 것도 같이 확인 한다.
3) System.out.println(tt instanceof MyCircle); true
상속관계가 맞으면 무조건 true 
4) System.out.println(obj instanceof MyPoint); false
부모는 자식을 .. 확인하지는 못 한다.
5) System.out.println(tt instanceof MyRectangle);  연관되지 않은 클래스와는 오류가 난다.

가장 많이 사용하는 예제는 2) 번이며 나머지 출력문은 오직 확인을 위한 예제 출력문이다. (잘 사용하지 않음)

 


eclips에서 클래스 생성시 상속 (extends ..) 바로 만드는 방법!