프로그래밍 언어/JAVA

[JAVA] 자바의 인터페이스 Interface

Rateye 2021. 1. 19. 15:00
728x90
반응형

인터페이스 Interface

  • 어떤 객체와 개발자 사이의 접점(중개) 역할
  • 인터페이스 정의 시 class 키워드 대신 interface 키워드를 사용
  • 인터페이스상수추상메서드만 가질 수 있음
    1. 상수 : public static final 을 사용하여 선언하며 생략도 가능
    2. 추상메서드 : public abstract 를 사용하여 정의하며 생략도 가능
  • 추상클래스와 마찬가지로 객체 생성이 불가능하며, 상속 전용으로 사용 단, 데이터타입으로는 사용 가능하므로, 다형성 활용 가능
  • 동일한 인터페이스를 구현하는 클래스를 사용하는 경우 하나의 인터페이스 타입으로 모든 객체를 컨트롤할 수 있다
  • 추상클래스보다 강제성이 더 강하다
    추상클래스는 일부 멤버(메서드)에 대한 강제성을 부여하지만 인터페이스는 모든 추상메서드와 상수에 대한 강제성을 부여

인터페이스 정의 기본 문법

[접근제한자] interface 인터페이스명 {
 		// 상수 선언
 		// 추상메서드 정의
 }
// 인터페이스 정의
public interface RemoteControl {
	// 인터페이스 내의 모든 변수는 상수(public static final) 로 취급됨
	public static final int MAX_VOLUME = 100; // 상수
	public static final int MIN_VOLUME = 0; // 상수
	
	int MAX_CHANNEL = 100; // 상수(public static final 생략되어 있음)
	public int MIN_CHANNEL = 1; // 상수(static final 생략되어 있음)
	
	// 인터페이스 내의 모든 메서드는 추상메서드(public abstract) 로 취급됨
	//	public void turnPower() {} // 중괄호{} 를 포함할 수 없다!
	public void turnPower(); // 추상메서드(abstract 생략되어 있음)
	
	public abstract void channelUp(); // 추상메서드
	public abstract void channelDown(); // 추상메서드
	public abstract void changeChannel(int channel); // 추상메서드 
	
	void volumeUp(); // 추상메서드(public abstract 생략되어 있음)
	void volumeDown(); // 추상메서드(public abstract 생략되어 있음)
	
}
// interfaces 패키지의 RemoteControl 인터페이스를 구현하는
// 구현체 클래스 Tv 를 정의
// => 클래스명 뒤에 implements 키워드를 쓰고 뒤에 인터페이스명을 지정
class Tv implements RemoteControl {
	boolean isPowerOn = false;
	
	// RemoteControl 인터페이스를 구현하기 위해 implements 할 경우
	// 인터페이스 내의 모든 추상메서드를 구현(오버라이딩)해야한다!
	@Override
	public void turnPower() {
		System.out.println("Tv 전원 상태 변경!");
	}

	@Override
	public void channelUp() {
		System.out.println("Tv 채널 증가!");
	}

	@Override
	public void channelDown() {
		System.out.println("Tv 채널 감소!");
	}

	@Override
	public void changeChannel(int channel) {
		System.out.println("Tv 채널 변경 - " + channel + "번!");
	}

	@Override
	public void volumeUp() {
		System.out.println("Tv 볼륨 증가!");
	}

	@Override
	public void volumeDown() {
		System.out.println("Tv 볼륨 감소!");
	}
	
	public void tvStatus() {
		System.out.println("전원 상태 : " + isPowerOn);
		System.out.println("최소 채널 : " + MIN_CHANNEL);
		System.out.println("최대 채널 : " + MAX_CHANNEL);
		System.out.println("최소 볼륨 : " + MIN_VOLUME);
		System.out.println("최대 볼륨 : " + MAX_VOLUME);
	}
	
}

class Audio implements RemoteControl {
	// RemoteControl 인터페이스를 구현하기 위해 implements 할 경우
	// 인터페이스 내의 모든 추상메서드를 구현(오버라이딩)해야한다!
	@Override
	public void turnPower() {
		System.out.println("Audio 전원 상태 변경!");
	}

	@Override
	public void channelUp() {
		System.out.println("Audio 채널 증가!");
	}

	@Override
	public void channelDown() {
		System.out.println("Audio 채널 감소!");
	}

	@Override
	public void changeChannel(int channel) {
		System.out.println("Audio 채널 변경 - " + channel + "번!");
	}

	@Override
	public void volumeUp() {
		System.out.println("Audio 볼륨 증가!");
	}

	@Override
	public void volumeDown() {
		System.out.println("Audio 볼륨 감소!");
	}
	
}
import interfaces.RemoteControl;

public class Ex4 {

	public static void main(String[] args) {

		Tv tv = new Tv();
		tv.turnPower();
		tv.tvStatus();
		
		Audio audio = new Audio();
		audio.turnPower();
		
		System.out.println("==================");
		
		// 인터페이스를 구현한 클래스가 존재하는 경우
		// 일반적으로 인터페이스 타입으로 업캐스팅 후에
		// 공통된 기능을 다형성으로 다루는 것이 보편적
		// => Tv & Audio 의 부모 인터페이스인 RemoteControl 타입 사용
		
		// 인터페이스는 인스턴스 생성(new) 불가능! = 추상클래스와 동일
//		RemoteControl remote = new RemoteControl();  
		
		// Tv -> RemoteControl 업캐스팅
		RemoteControl remote = new Tv(); // 업캐스팅 가능
		remote.turnPower();
		remote.channelUp();
		remote.channelDown();
		remote.volumeUp();
		remote.volumeDown();
		
		// Audio -> RemoteControl 업캐스팅
		remote = new Audio(); // 업캐스팅 가능
		remote.turnPower();
		remote.channelUp();
		remote.channelDown();
		remote.volumeUp();
		remote.volumeDown();
		
	}

}

 

다중 구현 implements

하나의 서브클래스가 둘 이상의 부모 인터페이스를 가질 수 있다.

여러 부모인터페이스의 모든 추상메서드를 오버라이딩

  • 인터페이스끼리도 상속이 가능

    인터페이스간의 상속은 implements 가 아닌 extends 를 사용 추상메서드를 구현하는 것이 목적이 아니기 때문

interface MyInterface1 {
	
	public static final int NUM1 = 10; // 상수
	
	public abstract void method1(); // 추상메서드
	
}

interface MyInterface2 {
	
	public static final int NUM2 = 20; // 상수
	
	public abstract void method2(); // 추상메서드
	
}

// MyInterface1, MyInterface2 인터페이스를 구현하는 서브클래스 SubClass 정의
class SubClass implements MyInterface1, MyInterface2 {

	// 부모 인터페이스로부터 상속받은 추상메서드 구현(오버라이딩) 필수
	@Override
	public void method1() {
		System.out.println("서브클래스에서 구현한 추상메서드 method1()");
	}

	@Override
	public void method2() {
		System.out.println("서브클래스에서 구현한 추상메서드 method2()");
	}
	
}
		SubClass sc = new SubClass();
		sc.method1(); // MyInterface1 의 추상메서드
		sc.method2(); // MyInterface2 의 추상메서드
		
		// 인터페이스도 instanceof 연산자의 판별 대상이 될 수 있다!
		// sc 는 MyInterface1 입니까? true
		if(sc instanceof MyInterface1) {
			System.out.println("sc 는 MyInterface1 입니다!");
		} else {
			System.out.println("sc 는 MyInterface1 이 아닙니다!");
		}
		
		// sc 는 MyInterface2 입니까? true
		if(sc instanceof MyInterface2) {
			System.out.println("sc 는 MyInterface2 입니다!");
		} else {
			System.out.println("sc 는 MyInterface2 가 아닙니다!");
		}
		
		// sc -> MyInterface1 타입으로 업캐스팅
		MyInterface1 mi1 = sc;
		mi1.method1(); // MyInterface1 이 가진 추상메서드
//		System.out.println(SubClass.NUM1); // MyInterface1 이 가진 상수
		System.out.println(MyInterface1.NUM1); // MyInterface1 이 가진 상수
		
		// sc -> MyInterface2 타입으로 업캐스팅
		MyInterface2 mi2 = sc;
		mi2.method2(); // MyInterface1 이 가진 추상메서드
		System.out.println(SubClass.NUM2); // MyInterface1 이 가진 상수

 

인터페이스 간의 상속과 클래스

// 2개의 부모인터페이스를 정의하고 하나의 인터페이스에서 모두 상속
interface ParentInterface1 {
	
	public abstract void parentMethod1();
	
}

interface ParentInterface2 {
	
	public abstract void parentMethod2();
	
}

// ChildInterface 인터페이스 정의 - ParentInterface1, ParentInterface2 상속
// 주의1. 인터페이스간의 상속은 extends 키워드 사용
// 주의2. 부모인터페이스를 상속받은 자식인터페이스에서 추상메서드 구현 없음
//        => 인터페이스 내에는 무조건 추상메서드만 존재해야하므로
interface ChildInterface extends ParentInterface1, ParentInterface2 {
	// 2개의 부모인터페이스(ParentInterface1, ParentInterface2)를 상속받으면
	// 부모인터페이스의 추상메서드와 자신의 추상메서드를 모두 갖게됨
	// 즉, parentMethod1(), parentMethod2() 추상메서드와
	public abstract void childMethod3(); // 자신의 추상메서드를 갖는다
	
}

// SubClass2 클래스 정의 - ChildInterface 인터페이스 구현
class SubClass2 implements ChildInterface {

	@Override
	public void parentMethod1() {
		System.out.println("서브클래스에서 구현한 parentMethod1()");
	}

	@Override
	public void parentMethod2() {
		System.out.println("서브클래스에서 구현한 parentMethod2()");
	}

	@Override
	public void childMethod3() {
		System.out.println("서브클래스에서 구현한 childMethod3()");
	}
	
}

// =============================================================
class ParentClass {
	
	public void normalMethod() {
		System.out.println("ParentClass 의 normalMethod()");
	}
	
}

// 하나의 서브클래스는 하나의 슈퍼클래스와 1개 이상의 인터페이스를
// 부모로 가질 수 있다.
// => 주의! extends 와 implements 동시 사용 시 extends 를 먼저 선언해야함
class SubClass3 extends ParentClass implements ChildInterface {

	@Override
	public void parentMethod1() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void parentMethod2() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void childMethod3() {
		// TODO Auto-generated method stub
		
	}
	
}
// =========================================================

//abstract class 동물 {
//	public abstract void 번식();
//}
//
//class 고래 extends 동물 {
//	@Override
//	public void 번식() {
//		System.out.println("새끼를 낳아 번식!");
//	}
//} 
//
//class 상어 extends 동물 {
//	@Override
//	public void 번식() {
//		System.out.println("알을 낳아 번식!");
//	}
//} 

// 만약, 클래스간의 다중 상속이 가능했다면 발생할 수 있는 문제
//class 고래상어 extends 고래, 상어 { // 실제로는 불가능하므로 오류 발생
//	// 만약, 고래상어 클래스 내에서 번식() 메서드를 호출하면
//	// 고래의 번식인가? 상어의 번식인가?
//	// => 다이아몬드 상속 관계에서의 문제(이슈)
//	//    하나의 부모로부터 두 자식이 상속을 받고
//	//    다시 하나의 손자가 두 자식으로부터 상속을 받을 경우
//	//    부모로부터 상속된 메서드를 두 자식이 구현하고
//	//    손자가 해당 메서드에 접근하려 할 때 
//	//    두 자식 중 누구의 메서드인지 구분할 수 없게 된다!
//	//    => 따라서, 자바에서 클래스간의 다중 상속은 불가능
//	public void 번식() {
//		super.번식(); // 고래.번식()? 상어.번식()? = 구별 불가능
//	}
//	
//}


// 인터페이스는 다중 상속이 가능한 이유
interface 동물 {
	public abstract void 번식();
}

interface 고래 extends 동물 {
	// 인터페이스를 상속받은 인터페이스에서는 구현의 강제가 발생하지 않음!
	// => 구현하고 싶어도 구현이 불가능
}

interface 상어 extends 동물 {}

class 고래상어 implements 고래, 상어 {

	// 하나의 부모인터페이스로부터 두 자식인터페이스가 상속을 받고
	// 다시 하나의 손자클래스가 두 자식인터페이스로부터 상속을 받을 경우
	@Override
	public void 번식() { 
		// 고래.번식()? 상어.번식()? 구분할 필요가 없음!!!
		// 동일한 추상메서드이므로 구분 필요없이 바디{} 만 구현하면 된다!
		System.out.println("알을 낳아 번식!");
	}
	
}
		고래상어 고래상어 = new 고래상어();
		고래상어.번식();
		동물 동물 = 고래상어;
		동물.번식();

인터페이스의 필요성(장점)구현의 강제로 표준화

1. 구현의 강제로 표준화

  • 추상메서드를 갖는 인터페이스를 서브클래스에서 상속받으면 반드시 추상메서드를 구현해야함 따라서, 개발자가 실수로 구현을 빠뜨릴 위험이 없다.

2. 모듈 교체가 쉬움

  • 인터페이스를 통해 업캐스팅을 사용하여 다형성을 적용시키면 단순한 모듈(객체) 교체만으로 동일한 코드를 사용하여 여러 객체를 다룰 수 있게 됨
  • 또한, 새로운 모듈이 추가되더라도 기존 인터페이스 구현체라면 별도의 코드 수정 없이 객체의 교체만으로 그대로 사용 가능
interface Printer {
	public void print(String fileName);
}

class LaserPrinter implements Printer {
	@Override
	public void print(String fileName) {
		System.out.println("LaserPrinter 로 출력중 - " + fileName);
	}
}

class DotPrinter implements Printer {
	@Override
	public void print(String fileName) {
		System.out.println("DotPrinter 로 출력중 - " + fileName);
	}
}

class PrintClient {
	private Printer printer; // 인터페이스 타입 참조변수 선언

	// 외부로부터 Printer 타입 인스턴스를 전달받아 초기화하는 Setter 정의
	public void setPrinter(Printer printer) {
		// Printer 타입으로 전달받을 수 있는 인스턴스는
		// LaserPrinter, DotPrinter 등 Printer 인터페이스를 구현한 구현체
		this.printer = printer;
	}
	
	public void print(String fileName) {
		// Printer 타입 객체 내의 print() 메서드를 호출하여
		// 전달받은 fileName 에 내용 출력하도록 요청
		printer.print(fileName);
	}
	
	public void printSetting() {
		System.out.println("프린터기 셋팅");
	}
	
}
		LaserPrinter lp = new LaserPrinter();
		lp.print("Ex.java");
		
		DotPrinter dp = new DotPrinter();
		lp.print("Ex.java");
		// ------------------------------
		// 일반적인 다형성 활용
		// 부모 인터페이스 타입으로 업캐스팅하여 사용
		// => 인터페이스 내에 존재하는 상수와 추상메서드에만 접근 가능
		Printer p = new LaserPrinter();
		p.print("Ex.java");
		
		p = new DotPrinter();
		p.print("Ex.java");
		// ------------------------------
		// PrintClient 인스턴스 생성
		// 별도의 클래스를 정의하여 부모 인터페이스 타입 객체를 전달받아 사용
		// => 인터페이스의 멤버 외에 별도의 클래스에서 정의한 멤버도 사용 가능
		PrintClient pc = new PrintClient();
		pc.setPrinter(new LaserPrinter());
		pc.print("Ex.java");
		pc.printSetting();
		
		pc.setPrinter(new DotPrinter());
		pc.print("Ex.java");
		pc.printSetting();
		
		// 만약, InkJetPrinter 가 추가되더라도 Printer 를 구현했다면
		// 별도로 PrintClient 클래스를 수정할 필요없이
		// setPrinter() 메서드 파라미터로 InkJetPrinter 객체만 교체하면
		// 얼마든 새로운 Printer 타입 객체를 다룰 수 있다!
//		pc.setPrinter(new InkJetPrinter());
//		pc.print("Ex.java");

3. 상속 관계가 없는 클래스끼리 관계 부여 가능 => 다형성 확장

  • 기존에 다른 클래스를 상속중일 때 다중 상속이 불가능한데 인터페이스를 활용하여 상속관계가 아닌 객체간에 공통 인터페이스 제공으로 새로운 상속 관계 부여가 가능
  • 관계가 없는 객체의 경우 공통 타입이 Object 타입뿐이므로 Object 타입으로 변환하여 관리는 할 수 있으나, 각 객체의 메서드 호출을 위해서는 다시 다운캐스팅이 필요하지만 인터페이스를 통해 상속 관계를 부여하고, 인터페이스에서 공통메서드를 추상메서드로 제공하는 경우에는 별도의 다운캐스팅 및 타입 판별 없이 바로 공통 메서드의 호출이 가능해짐
class Phone {}

class Camera {}

class HandPhone extends Phone {
	public void charge() {
		System.out.println("HandPhone 충전!");
	}
}

class DigitalCamera extends Camera {
	public void charge() {
		System.out.println("DigitalCamera 충전!");
	}
}

// --------------------------------------------------------------
// HandPhone 과 DigitalCamera 사이에 특정 관계를 부여해주기 위해
// 공통 인터페이스인 Chargeable 인터페이스 정의하고
// 해당 인터페이스 내에 추상메서드로 charge() 메서드를 정의
interface Chargeable {
	public abstract void charge();
}

// HandPhone2 클래스 정의 - Phone 클래스 상속, Chargeable 인터페이스 구현
class HandPhone2 extends Phone implements Chargeable {

	@Override
	public void charge() {
		System.out.println("HandPhone2 충전!");
	}
	
}

// DigitalCamera2 클래스 정의 - Camera 클래스 상속, Chargeable 인터페이스 구현 
class DigitalCamera2 extends Camera implements Chargeable {
	
	@Override
	public void charge() {
		System.out.println("DigitalCamera2 충전!");
	}
	
}
public class Ex4 {

	public static void main(String[] args) {
		
		Ex4 ex = new Ex4();
		ex.badCase();
		
		ex.goodCase();
	}
	
	// 상속관계가 아닌 객체들을 사용하여 다형성을 적용시켜야 할 경우
	public void badCase() {
		// HandPhone, DigitalCamera 의 공통 타입은 Object 타입밖에 없음
		// => 이 때, Object 타입으로 업캐스팅 시 charge() 메서드 호출 불가
//		Object obj = new HandPhone();
//		obj.charge(); // Object 타입으로 호출 불가능한 메서드
//		// 다운캐스팅 통해 다시 HandPhone 타입으로 변경해야 charge() 호출 가능
//		HandPhone hp = (HandPhone)obj;
//		hp.charge();
//		
//		obj = new DigitalCamera();
//		obj.charge(); // Object 타입으로 호출 불가능한 메서드
		
		// ------------------------------------------------------------
		// Object[] 타입으로 HandPhone, DigitalCamera 인스턴스를 관리
		Object[] objs = {new HandPhone(), new DigitalCamera()};
		
		// for문을 사용하여 배열 objs 의 모든 인스턴스에 차례대로 접근하여
		// 각각의 타입에 맞는 다운캐스팅 수행 후 charge() 메서드 호출
//		for(int i = 0; i < objs.length; i++) {
//			Object o = objs[i]; // 배열 데이터(객체) 꺼내기
//			if(o instanceof HandPhone) { // HandPhone 타입인지 판별
//				// HandPhone 타입으로 다운캐스팅 가능
//				HandPhone hp = (HandPhone)o;
//				hp.charge();
//			} else if(o instanceof DigitalCamera) { // DigitalCamera 타입 판별
//				// DigitalCamera 타입으로 다운캐스팅 가능
//				DigitalCamera dp = (DigitalCamera)o;
//				dp.charge();
//			}
//		}
		
		for(Object o : objs) {
			if(o instanceof HandPhone) { // HandPhone 타입인지 판별
				// HandPhone 타입으로 다운캐스팅 가능
				HandPhone hp = (HandPhone)o;
				hp.charge();
			} else if(o instanceof DigitalCamera) { // DigitalCamera 타입 판별
				// DigitalCamera 타입으로 다운캐스팅 가능
				DigitalCamera dp = (DigitalCamera)o;
				dp.charge();
			}
		}
		
	}
	
	// 상속관계가 아닌 객체들에게 인터페이스를 활용하여 
	// 상속관계를 부여한 후 다형성에 활용할 경우
	public void goodCase() {
		// HandPhone2, DigitalCamera2 객체를 담기 위한 타입이
		// Object 타입 외에 Chargeable 타입도 가능
		// => 따라서, Chargeable 타입 배열로 두 객체 관리가 가능
		Chargeable[] objs = {new HandPhone2(), new DigitalCamera2()};
		
		// for문을 사용하여 Chargeable[] 타입 내의 모든 객체에 접근하여
		// 상속받아 구현한 공통 메서드 charge() 메서드 호출
		// => Chargeable 인터페이스에 charge() 메서드가 존재하므로
		//    별도의 다운캐스팅 없이도 charge() 메서드에 접근 가능
		for(Chargeable obj : objs) {
			obj.charge(); // 공통메서드를 직접 호출 가능(다운캐스팅 불필요)
		}
		
	}

}

4. 모듈간 독립적 프로그래밍으로 개발 시간 단축

  • 여러 모듈간에 공통된 기능을 구현할 메서드를 인터페이스 내의 추상메서드로 제공하여 모듈간 통일성 부여
  • 각 모듈에서 추상메서드 구현을 통해 각자에게 필요한 기능을 따로 작업한 후 차후 결합 시 쉽게 결합 가능
  • 따라서, 상대방의 작업 진행 상황과 관계없이 개발이 가능하므로 개발 비용이 줄어드는 효과를 가져오게 된다
ex) 숫자 2개를 입력하여 합을 계산 후 결과를 화면에 출력하는 프로그램
디자이너(A) - 개발자(B) 협업 수행 가정했을 때 A 는 입력받은 데이터를 B 에 전달하고 결과값을 기다린 후 B 가 리턴하는 결과를 전달받아 화면에 출력해야하며, B는 A가 입력받은 데이터를 전달했을 때, 해당 데이터의 합계를 계산한 후 다시 A 에게 리턴해야한다. 이 때, 서로 상대방의 작업이 완료되지 않으면 다음 작업 수행이 불가능하므로 상호간에 작업 내용이 같이 진행되어야 한다. 따라서, 한 쪽에서 작업이 지연되면 다른쪽도 함께 지연되므로 작업에 소요되는 비용이 증가하게 됨 => 이를 해결하기 위해 인터페이스 적용 가능 A 입장 : "숫자 두 개 전달, 하나의 결과값(숫자) 리턴받아 출력" B 입장 : "숫자 두개 전달 받아 계산 후, 하나의 숫자 리턴"
interface Calculator {
	// 디자이너와 개발자 모두 사용할 공통 메서드를 추상메서드로 정의
	public int add(int a, int b);
}

// 디자이너 입장에서의 코드
class CalculatorDesigner {
	public void add() {
		// 외부로부터 두 개의 숫자를 입력받았다고 가정
		int a = 10, b = 20;
		
		// 개발자에게 두 정수를 전달한 뒤, 결과값으로 정수 1개 리턴받아 출력
		// => 현재 개발자 코드가 완성되지 않았더라도
		//    개발자가 사용할 메서드를 미리 구현한 클래스를 대신 사용 가능
		CalculatorDesignerDev cal = new CalculatorDesignerDev();
		int result = cal.add(a, b); // 입력받은 두 정수 전달 후 결과 리턴
		System.out.println(a + " + " + b + " 의 결과 = " + result);
		
		// ================================================================
		// 차후 개발자의 코드가 완성되면 해당 객체를 통해 add() 메서드 호출
		CalculatorDeveloper cal2 = new CalculatorDeveloper();
		int result2 = cal2.add(a, b); // 입력받은 두 정수 전달 후 결과 리턴
		System.out.println(a + " + " + b + " 의 결과 = " + result2);
		// ================================================================
		
	}
}

// 디자이너가 개발자에게 구현될 코드를 미리 간단히 작성하여 테스트 가능
class CalculatorDesignerDev implements Calculator {

	@Override
	public int add(int a, int b) {
		// 디자이너 입장에서는 전달받은 두 수를 
		// 어떻게 계산할 지는 중요하지 않으며, 단지 확인만 수행하면 됨
		System.out.println("전달된 파라미터 확인 a = " + a + ", b = " + b);
		return 0;
	}
	
}

// =============================================================
// 개발자 입장에서의 코드
class CalculatorDeveloper implements Calculator {
// 외부로부터 정수를 입력받는 코드는 중요하지 않고
// 전달받은 2개의 정수에 대한 덧셈을 수행한 후 리턴이 잘 되는지 확인만 필요

	@Override
	public int add(int a, int b) {
		System.out.println("전달받은 파라미터 : " + a + ", " + b);
		return a + b; 
	}
	
}
// 디자이너 입장에서의 코드(파라미터 및 리턴값) 확인
		CalculatorDesigner designer = new CalculatorDesigner();
		designer.add();
		
		// =======================================
		// 개발자 입장에서의 코드(파라미터 및 리턴값) 확인
		CalculatorDeveloper developer = new CalculatorDeveloper();
		int result = developer.add(100, 200);
		System.out.println("리턴값 확인 : " + result);
		
		String str = "";
728x90
반응형