본문 바로가기

JAVA/일반

자바/Java 상속 , interface의 다형성을 활용한 Print 인쇄하기

자바/Java 상속 , interface의 다형성을 활용한 Print 인쇄하기

▒ ▒  ▒  ▒  ▒  ▒  ▒  전체 소스 입니다. ▒ ▒  ▒  ▒  ▒  ▒  ▒  
package arabiannight.tistory.com;

public class TestInterface {

	public static void main(String[] args) {
		DotePrint dt = new DotePrint();
		InkPrint ip = new InkPrint();
		LaserPrint lp = new LaserPrint();
		dt.excutePrint(dt);
		ip.excutePrint(ip);
		lp.excutePrint(lp);
		System.out.println();
		dt.supplementInk(dt);
		ip.supplementInk(ip);
		lp.supplementInk(lp);
	}
}

interface Supplementable {} //잉크 충전 interface

class Print { //기본 프린트
	private int A4Size;  // A4용지 사이즈
	private int printSpeed;  // 인쇄 속도
	
	public Print(int size , int speed){
		this.A4Size = size;
		this.printSpeed = speed;
	}

	public int getA4Size(){	return this.A4Size;	}
	public int getPrintSpeed(){ return this.printSpeed; }

	public void excutePrint(Print p){ //인쇄 시작
		if(p instanceof Print){
			System.out.println(p.toString() + " 프린트로 인쇄 완료 되었습니다.");
			System.out.println("A4용지의 크기는 " + p.getA4Size() + " 입니다.");
			System.out.println("인쇄 속도는 " + p.getPrintSpeed() + " 입니다.");
		}
	}
	
	public void supplementInk(Supplementable s){ //잉크 충전
		if(s instanceof NeedInkPrint){
			NeedInkPrint np = (NeedInkPrint)s;
			if(np.getInkGage()!=np.getMaxInkGage()){
				np.setInkGage();
				System.out.println("잉크 충전이 완료 되었습니다.");
			}else{
				System.out.println("이미 충전이 완료 되어 있습니다. 확인 바랍니다.");
			}
		}else{
			System.out.println("잉크 충전 방식의 프린트가 아닙니다.");
		}
	}
}

class NeedInkPrint extends Print { //잉크 충전이 필요한 프린트
	private static final int MAX_INK_GAGE = 100;
	private int inkGage;
	public NeedInkPrint(int size, int speed, int ink) {
		super(size, speed);
		this.inkGage = ink;
	}
	
	public void setInkGage(){ this.inkGage = MAX_INK_GAGE; }
	public int getInkGage(){ return this.inkGage; }
	public static int getMaxInkGage(){ return MAX_INK_GAGE; }
}

class DotePrint extends NeedInkPrint implements Supplementable{ //도트 프린트
	public DotePrint() {
		super(80, 30, 100);
	}
	public String toString(){
		return "도트";
	}
}

class InkPrint extends NeedInkPrint implements Supplementable{ //잉크젯 프린트
	public InkPrint() {
		super(80, 60, 63);
	}
	public String toString(){
		return "잉크젯";
	}
}

class LaserPrint extends Print implements Supplementable{ //레이져 프린트
	public LaserPrint() {
		super(80, 100);
	}
	public String toString(){
		return "레이져";
	}
}

▒ 실행결과.  
도트 프린트로 인쇄 완료 되었습니다.
A4용지의 크기는 80 입니다.
인쇄 속도는 30 입니다.
잉크젯 프린트로 인쇄 완료 되었습니다.
A4용지의 크기는 80 입니다.
인쇄 속도는 60 입니다.
레이져 프린트로 인쇄 완료 되었습니다.
A4용지의 크기는 80 입니다.
인쇄 속도는 100 입니다.

이미 충전이 완료 되어 있습니다. 확인 바랍니다.
잉크 충전이 완료 되었습니다.
잉크 충전 방식의 프린트가 아닙니다.


▒ ▒  ▒  ▒  ▒  ▒  ▒  Detail 소스 설명 입니다.  ▒ ▒  ▒  ▒  ▒  ▒  ▒

에고 갑자기 인터페이스 부분 보다가 코딩해봤습니다 --;;
새벽 2시가 넘었다는 졸렵네요 ㅎㅎ 필요하신분들은 퍼가시구요 ㅎㅎ!!
힘들게 생각하면서 짯는데 혹 아주 조금이나마 도움이 되셨다면!! 응원댓글 하나만 남겨주세요 ㅎㅎ!!!

감사합니다!! ㅎㅎ


▒ 1. 
기본적으로 세개의 프린트의 기본이 되는 프린트 입니다.
세개의 프린트에 공통으로 들어가는 기능이나 상태를 뽑아서 Print라는 클래스를 만들었습니다.

class Print { //기본 프린트
	private int A4Size;  // A4용지 사이즈
	private int printSpeed;  // 인쇄 속도
	
	public Print(int size , int speed){
		this.A4Size = size;
		this.printSpeed = speed;
	}

	public int getA4Size(){	return this.A4Size;	}
	public int getPrintSpeed(){ return this.printSpeed; }

	public void excutePrint(Print p){ //인쇄 시작
		if(p instanceof Print){
			System.out.println(p.toString() + " 프린트로 인쇄 완료 되었습니다.");
			System.out.println("A4용지의 크기는 " + p.getA4Size() + " 입니다.");
			System.out.println("인쇄 속도는 " + p.getPrintSpeed() + " 입니다.");
		}
	}
	
	public void supplementInk(Supplementable s){ //잉크 충전
		if(s instanceof NeedInkPrint){
			NeedInkPrint np = (NeedInkPrint)s;
			if(np.getInkGage()!=np.getMaxInkGage()){
				np.setInkGage();
				System.out.println("잉크 충전이 완료 되었습니다.");
			}else{
				System.out.println("이미 충전이 완료 되어 있습니다. 확인 바랍니다.");
			}
		}else{
			System.out.println("잉크 충전 방식의 프린트가 아닙니다.");
		}
	}
}


▒ 2. 
excutePrint의 매개변수를 Print Class의 참조 변수로 받아서 Print 인스턴스를 상속받고 있는 클래스들의 인스턴스를 사용 할 수 있게 하였습니다. (도트, 잉크젯, 레이져)프린트 모두 결국에는 Print 클래스를 상속 받고 있기 때문에, Print 클래스의 참조 변수로 세 프린트의 인스턴스에 접근이 가능 하단 이야기 입니다.

아래를 보시면 (p instanceof Print) 라는 부분이 보이는데 이부분은 (Print p) 에서 매개변수로 받은 Print 형식의 p라는 참조변수가 참조하고 있는 객체를 Print의 참조변수로 참조하여 사용 할 수 있나 확인 하는 작업입니다.

매개변수 p로 받은 부분은 기본프린트, 도트, 잉크젯, 레이져 프린트 등 Print를 상속받은 클래스들을 참조하고 있는 참조변수가 넘어오겠죠? 거기서 Print 인스턴스를 실질적으로 사용할 수 있는 참조 변수 여부를 가려내는 작업입니다.

만약 (p instanceof Print) 의 참조변수 p가 참조하는 인스턴스가 Print의 참조변수로 사용할 수 있다면 if 절 안의 내용이 실행되겠죠? 

( A instanceof B ) = B가 A의 조상일 경우 무조건 True의 결과를 얻습니다.
 
public void excutePrint(Print p){ //인쇄 시작
		if(p instanceof Print){
			System.out.println(p.toString() + " 프린트로 인쇄 완료 되었습니다.");
			System.out.println("A4용지의 크기는 " + p.getA4Size() + " 입니다.");
			System.out.println("인쇄 속도는 " + p.getPrintSpeed() + " 입니다.");
		}
	}


▒ 3. 

마찬가지로 매개변수의 다형성 처럼 인터페이스를 구현한 클래스들의 다형성을 이용하는 부분 입니다.
여기서는 잉크를 사용하는 프린터들을 구별하는 작업 해주고 있습니다.
interface Supplementable {} //잉크 충전 interface
public void supplementInk(Supplementable s){ //잉크 충전
		if(s instanceof NeedInkPrint){
			NeedInkPrint np = (NeedInkPrint)s;
			if(np.getInkGage()!=np.getMaxInkGage()){
				np.setInkGage();
				System.out.println("잉크 충전이 완료 되었습니다.");
			}else{
				System.out.println("이미 충전이 완료 되어 있습니다. 확인 바랍니다.");
			}
		}else{
			System.out.println("잉크 충전 방식의 프린트가 아닙니다.");
		}
	}


▒ 4.  
Print 클래스를 모두 상속 받았기 때문에
excutePrint(Print p)에 해당 프린트의 참조 변수를 넣으면 실행 됩니다. supplementInk(Supplementable s) 메서드 또한 매개변수로 interface를 받고 있기때문에 , 
Supplementable 를 구현한 클래스들의 참조변수를 넣어 실행 할 수 있습니다.
여기서는 테스트를 위해 모든 프린터에  Supplementable 인터페이스를 구현 시켰지만, 
정말로 잉크 충전을 사용하는 클래스 DotePrint와 InkPrint 만 Supplementable 인터페이스를 구현 시켜주면 되겠습니다. 
public class TestInterface {

	public static void main(String[] args) {
		DotePrint dt = new DotePrint();
		InkPrint ip = new InkPrint();
		LaserPrint lp = new LaserPrint();
		dt.excutePrint(dt);
		ip.excutePrint(ip);
		lp.excutePrint(lp);
		System.out.println();
		dt.supplementInk(dt);
		ip.supplementInk(ip);
		lp.supplementInk(lp);
	}
}


▒ 파일 첨부. 


Test_Java.zip