< 추상클래스를 이용해서 차트 만들기 >
-Chart 인터페이스
public interface Chart { //인터페이스(표준)- 꼭 가져야 하는 메소드 선언
// 데이터 전달받는기능, 타이틀 전달받는기능, 열이름 전달받는기능
void setData(int[] data);
void setTitle(String title);
void setColumnNames(String[] columnNames);
void drawChart();
}
-AbstractChart 추상클래스 (공통기능 구현)
/**
* Chart 인터페이스에 정의된 기능 중 모든 하위 클래스들이 공통으로 구현하는 기능들을 미리 구현하는 추상클래스
* <p>Chart 인터페이스를 구현하는 다양한 차트 구현 클래스는 Chart 인터페이스를 직접 구현하기보다는
* AbstractChart 추상 클래스를 상속받으면 빠르게 차트 구현 클래스를 작성할 수 있다.
* @author wnnns
*
*/
public abstract class AbstractChart implements Chart { //추상메소드도 포함하니까 abstract 붙임
private String title;
private String[] columnNames;
private int[] data;
@Override
public void setTitle(String title) { //값들을 대입하기 위해 setter메소드
this.title = title;
}
@Override
public void setColumnNames(String[] columnNames) {
this.columnNames = columnNames;
}
@Override
public void setData(int[] data) {
this.data = data;
}
public String getTitle() { //값들을 꺼내갈 수 있도록 getter 메소드
return title;
}
public String[] getColumnNames() {
return columnNames;
}
public int[] getData() {
return data;
}
}
-BarChart (다른 부분만 구현)
/**
* Chart 인터페이스를 구현하는 구현 클래스
* <p> Chart 인터페이스를 직접 구현하는 대신, Chart 인터페이스의 추상화된 메소드를 미리 구현하고 있는
* AbstractChart 추상클래스를 상속받아서 구현하는 클래스
* <p> Chart 인터페이스를 직접 구현하는 것보다 AbstractChart 추상클래스를 상속받아서 구현하는 것이
* 훨씬 빠르게 차트구현클래스를 작성하는 방법이다
*/
public class BarChart extends AbstractChart { //AbstractChart를 상속받음
/**
* 차트 데이터를 막대그래프로 표현하는 메소드
* <p> AbstractChart 추상클래스에 미구현한 추상메소드를 구현
* <p> 차트 데이터를 그래프로 표현하는 방식이 각 구현 클래스마다 모두 다르기 때문에, 해당 기능은 각각의 구현클래스에서 직접 구현
*/
public void drawChart() {
String title = getTitle();
String[] columnNames = getColumnNames();
int[] data = getData();
System.out.println("### BarChart ###");
System.out.println("<<" + title + ">>");
for(int index=0; index<columnNames.length; index++) { //'columnNames'배열의 길이만큼 반복
System.out.print("[" + columnNames[index] + "]"); // columnNames배열의 index번째를 꺼내기
for(int value=0; value<data[index]; value++) { //'data'배열의 각 값만큼 반복
System.out.print("■");
}
System.out.println();
}
}
}
-LineChart (다른 기능 구현)
public class LineChart extends AbstractChart {
public void drawChart() {
String title = getTitle();
String[] columnNames = getColumnNames();
int[] data = getData();
System.out.println("### LineChart ###");
System.out.println("<< "+title+" >>");
for(int index=0; index<columnNames.length; index++) {
System.out.print("["+columnNames[index]+"]");
for(int value=0; value<data[index]; value++) {
System.out.print(" ");
}
System.out.println("|");
}
}
}
-실행
public class ChartApp {
public static void main(String[] args) {
Chart chart = new BarChart(); // 여기서 객체 변경
chart.setData(new int[] {10, 25, 7, 30});
chart.setTitle("2021년 분기별 순이익 (단위: 억원)");
chart.setColumnNames(new String[] {"1분기", "2분기", "3분기", "4분기"});
chart.drawChart();
}
}
### BarChart ###
<< 2021년 분기별 순이익 (단위: 억원)>>
[1분기]■■■■■■■■■■
[2분기]■■■■■■■■■■■■■■■■■■■■■■■■■
[3분기]■■■■■■■
[4분기]■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
추상클래스를 사용하는 또다른 목적
<추상화클래스를 이용해서 ATM 기능 구현하기>
ex) 전산시스템의 '이체하기' 기능
1. ATM기의 연결요청 수락
2. 수신 메세지 처리
~~~ 기능마다 다른 작업 수행 ~~~ ---> 작업마다 변하는 부분
3. 처리결과 전송
4. 연결해제 ---> 작업마다 변하지 않는 부분
atm의 공통된 기능(변하지 않는 부분)을 먼저 추상화클래스에서 작성
얘네의 실행순서가 중요한데, 또 엄청 복잡한 실행순서를 갖고있는거야
그럼 처리하기라는 메소드 안에 순서대로 적음
(추상화 클래스 내의 하나의 메소드 안에 적음)
1. 연결요청수락하기();
2. 수신메세지처리하기();
3. 처리결과전송하기();
4. 연결해제하기();
이 사이에 빠져있는 것 = 업무로직 수행하기
얘는 각각 다르게 기능하니까 추상화메소드로만 만들어놓고 -> 이체작업 구현클래스에서 재정의
public abstract class Banking { //추상화클래스
public void 처리하기() { //처리하기 메소드의 수행순서
연결요청수락하기();
수신메세지처리하기();
업무로직수행하기();
처리결과전송하기();
연결해제하기();
}
// 변하는 부분을 추상화
public abstract void 업무로직수행하기();
// 변하지 않는 부분은 구현
private void 연결요청수락하기() {
System.out.println("### ATM 기기의 연결 요청을 수락한다.");
System.out.println("### ATM 기기와 연결을 유지한다.");
}
private void 수신메세지처리하기() {
System.out.println("### ATM 기기가 전송한 메세지를 읽어온다.");
System.out.println("### 수신된 암호화된 메세지의 유효성을 체크한다.");
System.out.println("### 수신된 암호화된 메세지를 복호화해서 평문으로 변환한다.");
}
private void 처리결과전송하기() {
System.out.println("### 처리결과를 암호화된 메세지로 변환한다.");
System.out.println("### 암호화된 메세지를 ATM으로 전송한다.");
}
private void 연결해제하기() {
System.out.println("### ATM 기기와의 연결을 해제한다.");
}
}
<추상클래스를 템플릿으로 활용>
- Banking 추상클래스 // 인터페이스에서 추상화한 공통 메소드를 구현,
// 각 구현 클래스마다 달라야 하는 메소드를 추상화함
- Transaction(이체작업) 구현클래스 // Banking 추상클래스를 상속받음 (공통메소드를 받기 위해)
추상클래스에서 추상화한 메소드를 메소드 재정의를 통해 구현
- 은행전산시스템 - Banking banking; // 구현 클래스를 만들어서 얘한테 전달을 해줄거야
// 그래서 Transaction 클래스를 만들었는데 Banking밖에 못받네?
클래스형변환 (Transaction -> Banking)
banking.처리하기( ); // Banking 추상클래스를 참조하게 되고, 처리하기 메소드를 호출하면
순서대로 실행하다가, 업무로직수행하기는 재정의된 메소드를 실행
- 변하지 않는 공통 메소드는 미리 만들어 놓고, 변하는 메소드만 때에 따라 구현해서 넣는 것 => 템플릿 패턴
<템플릿 클래스의 특징>
- 추상 클래스로 템플릿 클래스를 작성하면 구현 클래스의 구현부담을 감소시킬 수 있다.
- 템플릿 클래스에는 업무에 따라서 변하는 부분과 업무에 상관없이 변하지 않는 부분을 구분해서
전자는 추상메소드로, 후자는 구현메소드로 작성
- 템플릿 클래스로 상속받은 각 업무별 구현클래스에는 해당 업무에 맞에 추상메소드만 정의하면 된다.
(구현 클래스의 구현부담 최소화)
- 템플릿 클래스를 이용하면 복잡한 절차를 가진 업무를 구현할 때
실행순서에 맞게 해당 작업을 실행시키는 메소드를 미리 정의해 둘 수 있어서
개발자가 복잡한 절차를 일일이 구현할 필요가 없다.
-AbstractBanking banking;
추상화클래스에 변하지 않는 부분들을 구현해놓고, 연결잭으로 만듦
이 추상화클래스를 상속받은 다양한 기능의 구현클래스들 생성
이체 구현 클래스, 입금 구현 클래스, 계좌신설 구현 클래스 ...
이체할 때는 이체 구현클래스를 바라보고
계좌 신설할 때는 계좌신설 구현클래스를 바라보고 ...
객체가 매번 달라지게 만드는 것
실제로 전해준건 Transaction인데 얘는 Banking밖에 못받아서
얘를 바라보고
그 안에 있는 Banking을 실행하는 중에 재정의된 메소드가 있으면 그걸 실행
-추상화클래스
public abstract class AbstractBanking { //추상화클래스
public void process() { //처리하기 메소드와 수행순서
receive();
connect();
business();
send();
disconnect();
}
// 변하는 부분을 추상화
public abstract void business();
// 변하지 않는 부분은 구현
private void receive() {
System.out.println("### ATM 기기의 연결 요청을 수락한다.");
System.out.println("### ATM 기기와 연결을 유지한다.");
}
private void connect() {
System.out.println("### ATM 기기가 전송한 메세지를 읽어온다.");
System.out.println("### 수신된 암호화된 메세지의 유효성을 체크한다.");
System.out.println("### 수신된 암호화된 메세지를 복호화해서 평문으로 변환한다.");
}
private void send() {
System.out.println("### 처리결과를 암호화된 메세지로 변환한다.");
System.out.println("### 암호화된 메세지를 ATM으로 전송한다.");
}
private void disconnect() {
System.out.println("### ATM 기기와의 연결을 해제한다.");
}
}
-구현클래스
public class TransactionBanking extends AbstractBanking { //추상클래스를 상속받은 구현클래스
@Override
public void business() {
System.out.println("---------------------------------------------------");
System.out.println("### 이체작업 시작");
System.out.println("### 1. 수신메세지에서 이체정보 획득");
System.out.println("### 2. 잔액 확인 및 비밀번호 확인");
System.out.println("### 3. 상대방 계좌에 이체금액 송금");
System.out.println("### 4. 내 계좌의 잔액 변경 ");
System.out.println("### 5. 이체 내역정보 저장");
System.out.println("### 이체작업 종료");
System.out.println("---------------------------------------------------");
}
}
-은행 전산 시스템 클래스 (개발자가 개발하려는 프로그램)
/**
* 은행 전산 시스템 클래스
* <p> 은행 업무에 맞는 다양한 AbstractBanking 구현 객체를 전달받아서 실행시킨다.
* 이체하기, 출금하기, 계좌신설하기 등의 객체를 전달받음
* @author wnnns
*
*/
public class BankingSystem {
private AbstractBanking banking; // 부모객체를 연결잭으로 (어떤 객체를 연결할지 아직 몰라)
public void setBusinessBankingComponent(AbstractBanking banking) { // 어떤 구현 객체를 전달받아서 연결
this.banking = banking; // 전달받은 구현 객체의 구현메소드로 세팅
}
public void runBankingProcess() { // 추상화클래스의 구현메소드 실행
banking.process();
}
}
-실행객체 (외부시스템)
public class BankingApp {
public static void main(String[] args) {
BankingSystem system = new BankingSystem(); //얘를 통해 연결하니까 객체생성 필
TransactionBanking banking = new TransactionBanking(); //추상메소드를 구현한 객체 중 이체 기능
system.setBusinessBankingComponent(banking);
system.runBankingProcess();
}
}
### ATM 기기의 연결 요청을 수락한다.
### ATM 기기와 연결을 유지한다.
### ATM 기기가 전송한 메세지를 읽어온다.
### 수신된 암호화된 메세지의 유효성을 체크한다.
### 수신된 암호화된 메세지를 복호화해서 평문으로 변환한다.
---------------------------------------------------
### 이체작업 시작
### 1. 수신메세지에서 이체정보 획득
### 2. 잔액 확인 및 비밀번호 확인
### 3. 상대방 계좌에 이체금액 송금
### 4. 내 계좌의 잔액 변경
### 5. 이체 내역정보 저장
### 이체작업 종료
---------------------------------------------------
### 처리결과를 암호화된 메세지로 변환한다.
### 암호화된 메세지를 ATM으로 전송한다.
### ATM 기기와의 연결을 해제한다.
<상속과 구현 정리>
- 상속
- 부모클래스의 공개된 속성과 공개된 기능을 물려받는다.
- 자식클래스를 빠르게 정의할 수 있다.
- 같은 부모클래스를 상속받은 자식클래스는 모두 같은 부모타입으로 클래스 형변환이 가능하다.
- 같은 타입을 가지는 하위 클래스를 여러 개 정의하는 것이다.
- 클래스와 클래스의 결합도가 가장 높은 결합을 만든다.
- 부모의 속성과 기능을 전부 물려받는다.
(선별해서 상속받는 것 불가능) - 클래스를 작성할 때 상속관계는 되도록 피하는 게 좋다.
(선별을 할 수 없으니 되도록 지양)
- 구현 (인터페이스를 구현하는 것)
- 사용방법이 같은 하위 구현클래스를 작성하게 한다.
- 인터페이스를 이용한 구현은 클래스와 클래스의 결합도를 느슨하게 만든다.
- 구현은 필요한 사양이 정의된 인터페이스만 구현할 수 있다.
(인터페이스 분리원칙) -> 불필요한 구현 x - 하위 구현 클래스의 구현부담을 줄이기 위해서 추상 클래스를 정의하고, 추상 클래스를 상속받아서 하위 구현 클래스를 작성하는 경우가 많다. (상속은 주로 이럴 때 쓰임)
- 구현도 상속과 마찬가지로 같은 인터페이스를 구현한 구현 클래스는 전부 같은 인터페이스 타입으로 클래스 형변환이 가능하다.
- 하위 클래스를 정의할 때는 상속보다 구현을 활용하자.
<자바의 객체지향>
- 클래스
- 객체를 생성하는 설계도
- 구성요소 : 필드(멤버변수, 클래스변수), 생성자, 메소드(멤버메소드, 클래스메소드)
- 멤버변수 : 객체의 속성 담당. 그 객체가 가지는 고유한 정보 표현
- 생성자 : 클래스의 이름과 같은 이름으로 작성하는 메소드.
객체 생성 직후에 자동으로 실행되는 메소드.
객체의 초기화 담당
(멤버변수의 초기화, 본격적인 업무로직 실행 전에 수행할 전처리작업 실행)
- 멤버메소드 : 객체의 기능 담당. 객체와 객체는 다른 객체의 멤버메소드를 실행함으로써 서로 소통함.
객체를 생성하거나 객체를 획득하는 주요 이유가 멤버메소드의 실행을 위해서이다.
- 객체
- 클래스를 이용해서 메모리에 생성된 것(실체는 알 수 없음)
- 클래스에 정의된 속성과 기능을 사용하기 위해서는 반드시 그 클래스로 만들어진 객체가 필요하다.
- 객체는 그 객체의 참조값을 가지고 있는 참조변수를 통해서만 접근(사용)할 수 있다.
- 객체는 그 객체를 참조하는 참조변수가 하나도 없으면 가비지가 된다.
- 객체를 변수에 대입하는 것, 객체를 매개변수의 인자로 전달하는 것은 모두 그 객체의 주소값을 대입, 전달하는 것
- 멤버변수
- 클래스의 구성요소
- 객체가 생성되면 값이나 다른 객체의 주소값을 담는 변수가 생성된다.
- 객체가 생성될 때마다 각 객체마다 내부에 새로 생성된다.
- 객체가 유지되는 동안 멤버변수는 사라지지 않는다.
- 같은 클래스로 생성된 객체라도 멤버변수의 값은 서로 다를 수 있다.
- 객체의 모든 생성자, 모든 멤버메소드에서 멤버변수를 사용할 수 있다.
- 멤버메소드
- 클래스의 구성요소
- 객체의 고유한 기능을 담당한다.
- 멤버변수와 밀접하게 연관되어 있다.
- 메소드 중복정의, 생성자 중복정의
- 하나의 클래스 안에 같은 이름을 가지는 메소드를 여러 개 정의하는 것
조건) 메소드 매개변수의 타입, 매개변수의 개수가 서로 달라야 함. - 매개변수만 다르고 수행하는 작업은 비슷한 기능들을 같은 이름의 메소드로 정의하는 것이 목적.
- 비슷한 작업은 같은 이름의 메소드로 구현하자!
- 생성자 중복정의
- 생성자도 메소드의 일종이기 때문에 중복정의가 가능
- 생성자 중복정의는 객체를 생성하는 방법을 다양하게 만들 수 있다.
- 예시
* new String( )
// String객체 생성하고, 기본생성자를 실행하면 빈 문자열을 포함하고 있는 String객체 생성
// String src = "ABC";
* new String(String str)
// String객체 생성하고, 문자열을 전달받는 생성자를 실행하면 전달된 문자열을 값으로 가지는 String 객체 생성
// String src = new String("ABC");
* new String(byte[ ] bytes)
// String객체 생성하고, byte배열을 전달받는 생성자를 실행하면 전달된 byte배열의 값을 문자열로 가지는 String객체 생성
// String src = new String(new byte[] {65, 66, 67});
* new String(char[ ] chars)
// String객체 생성하고, char배열을 전달받는 생성자를 실행하면 전달된 char배열의 값을 문자열로 가지는 String객체 생성
// String src = new String(new char[] {'A', 'B', 'C'});
- 하나의 클래스 안에 같은 이름을 가지는 메소드를 여러 개 정의하는 것
- 상속
- 상위클래스를 상속받아서 하위클래스를 만드는 것이다.
- 상속이 필요한 순간
- 여러 종류의 하위 클래스에서 동일한 속성과 동일한 기능이 발견되면,
동일한 속성과 동일한 기능만 별도의 상위 클래스로 만들고, 그 상위 클래스를 상속받아서 하위클래스를 정의
- 여러 종류의 클래스들을 하나의 타입으로 관리할 필요가 있을 때, 상위클래스를 만들고 상위클래스를 상속받아서 하위클래스를 정의하면 하위클래스들은 모두 같은 상위클래스타입으로 관리할 수 있다.
- 클래스 형변환
- 하위 클래스타입의 객체를 상위 클래스타입의 참조변수로 참조하는 것
- 예시)
Phone p = new SmartPhone( );
Phone p = new Iphone( );
Person p = new Professor( );
Person p = new Employee( );
public void test(Phone p) { ... } <-- .test(new Phone( )); .test(new SmartPhone( )); .test(new Iphone( ));
Person[ ] p = new Person[ ] {new Employee( ), new Student( ), new Professor( ); new Employee( )};
- 메소드 재정의
- 상속관계에 있는 상위클래스와 하위클래스에서, 상위클래스로부터 물려받은 메소드를 하위클래스에서 같은 이름으로 다시 정의하는 것
- 조건)
접근제한자는 동일하거나 더 느슨한 것, 반환타입/메소드이름/매개변수의 타입과 순서,개수가 동일해야 함 - 목적)
- 상위클래스로부터 물려받은 기능이 하위클래스와 맞지 않으면 메소드를 재정의한다.
- 클래스 형변환되어서 상위클래스 타입으로 참조할 때, 하위 클래스에 정의된 메소드는 실행할 수 없지만,
메소드 재정의된 메소드는 상위클래스 타입을 참조하고 있어도 실행할 수 있다.
- 추상화
- 메소드의 구현부를 작성하지 않는 것
- 목적)
- 하위 구현 클래스에서 부모(상위 클래스나 인터페이스)에 선언된 메소드를 반드시 재정의하게 한다.
- 하위 구현 클래스들이 부모에서 선언된 메소드와 같은 사용법을 가지는 메소드로 기능을 구현하게 할 수 있다.
- 따라서, 클래스 형변환된 상태에서도 하위 구현 클래스에 재정의된 메소드를 실행할 수 있게 된다.
- 인터페이스
- 하위 구현 클래스가 반드시 구현할 기능의 사양을 정의
- 상수와 추상메소드만 보유 가능
- new 연산자로 객체를 생성할 수 없다
- 목적)
- 사용방법이 동일한 하위클래스를 만들게 하는 것이 목적
- 클래스와 클래스 간의 결합도를 느슨하게 만든다.
(클래스에서 인터페이스를 참조하고, 인터페이스를 구현한 객체들이 있을 때,
클래스에서 인터페이스를 참조하고 있지만, 요구하는 것은 인터페이스를 구현한 객체들임)
- 추상클래스
- 추상 메소드를 보유할 수 있는 클래스
- 일반 메소드와 완전히 동일한 구성요소를 가지며, 추상 메소드를 가질 수 있는 것만 다르다.
- new 연산자로 객체 생성할 수 없다.
- 목적)
- 하위 구현클래스의 구현부담을 감소시키는 것이 목적
- 일반적으로 인터페이스-추상클래스-하위구현클래스의 관계를 가지는 경우가 많다.
- 다형성
- 같은 방법으로 실행하지만 참조하는 객체가 달라지면 실행결과가 다르게 발현되는 것
- 다형성이 발휘되기 위한 조건
- 객체를 참조하는 참조변수는 상위 클래스나 인터페이스 타입이어야 한다.
(다양한 하위클래스 타입의 객체를 참조할 수 있다.)
- 실제로 사용하는 객체를 직접 생성하지 않고 전달받는다. (setter 메소드)
(Chart chart = new BartChart(); 이런식으로 직접 생성하면, 다른 객체 연결하고 싶을 때 코드를 바꿔야함)
- 실행하는 메소드는 메소드 재정의 관계에 있는 메소드여야 한다.
(상위타입의 객체를 참조하고 있어도 실제 생성된 하위객체의 재정의된 메소드를 실행할 수 있다.)
- 참조변수가 참조하는 객체들은 모두 사용방법이 동일해야 한다.
<다형성 구현하기 - 제일 많이 쓰는 형태>
- Company 클래스 : Chart인터페이스에 의존하고 있음 (의존관계-마름모)
- AbstractChart 추상클래스 : Chart인터페이스를 구현(메소드 재정의)하고 있음 (구현관계-점선삼각형)
- BarChart, LineChart 구현클래스 : AbstractChart를 상속받아서 다른 기능을 하는 메소드를 구현 (상속관계-실선삼각형)
- 실제로 Company클래스의 chart에서 쓰는 것은 구현클래스
근데 이 BarChart라는 이름이 Company클래스에 등장하지 않음 -> 얘네에 의존하지 않는다는 뜻 -> 그래서 Bar를 넣어도 Line을 넣어도 되는 것
(참조변수는 상위 클래스나 인터페이스 타입이어야 한다 -> 객체 교체를 위해(뭐가 와도 상관없으니까))
- 그러면 이제 Company클래스 안에 reporting이라는 실행 메소드 생성
-> 인터페이스 관점에서 코딩하는 것임 (인터페이스를 보고 코딩해야 함)
-> 의존관계가 인터페이스를 바라봐야 하고 , 기능들은 인터페이스에 정의된 기능을 보고 써야 다형성 발휘
-> Company가 사용하는 객체는 직접 생성하지 않고 외부로부터 전달받음-> set메소드 이용해서 전달
- 제3자가 등장(Company와 Chart를 조립하는 외부 시스템) - ChartApp
Conpany, Chart 를 모두 하나로 연결
제3의 존재에 의해서 조립(의존하는 객체를 전달)
company.setChart(barChart);
내가 전달한건 하위객체인 BarChart인데 setChart의 매개변수는 Chart타입만 받아
-> Chart타입을 참조함 -> 메소드 재정의에 의해 BarChart에 있는 메소드가 실행됨
-Chart 인터페이스
public interface Chart { //인터페이스(표준)- 꼭 가져야 하는 메소드 선언
void setData(int[] data);
void setTitle(String title);
void setColumnNames(String[] columnNames);
void drawChart();
}
-Company 클래스
import day15.chart.Chart;
public class Company {
// Company클래스는 Chart 인터페이스에 의존 (Company클래스와 Chart 구현 클래스의 관계를 느슨하게 하기)
private Chart chart; //여기에 어떤 차트가 전달되느냐에 따라서 달라짐
// Company클래스는 Chart 인터페이스를 구현한 객체를 직접 생성하지 않고, 외부로부터 전달받는다. (의존성 주입받기)
public void setChart(Chart chart) {
this.chart = chart; //이 메소드를 통해서 전달받는 객체가 달라짐!
}
public void reporting() {
// Company의 메소드에서는 Chart 인터페이스에 정의된 기능을 실행한다. (인터페이스 관점에서 코딩)
chart.drawChart();
}
}
-Company와 Chart를 조율하는 외부시스템
import day15.chart.BarChart;
import day15.chart.LineChart;
import utils.KeyboardReader;
public class CompanyApp { // 외부시스템(company, chart를 조율하는)
public static void main(String[] args) {
KeyboardReader keyboard = new KeyboardReader();
String title = "분기별 매출 보고서";
String[] names = {"1분기", "2분기", "3분기", "4분기"};
int[] data = {20, 7, 3, 10};
Company company = new Company(); // Company객체 미리 만듦
BarChart barChart = new BarChart(); // BarChart객체 미리 만듦
barChart.setTitle(title);
barChart.setColumnNames(names);
barChart.setData(data);
LineChart lineChart = new LineChart(); // LineChart객체 미리 만듦
lineChart.setTitle(title);
lineChart.setColumnNames(names);
lineChart.setData(data);
while(true) {
System.out.println("-----------------------------------");
System.out.println("1.차트변경 2.보고서출력 0.종료");
System.out.println("-----------------------------------");
System.out.println();
System.out.print("메뉴 선택: ");
int menuNo = keyboard.getInt();
System.out.println();
if(menuNo == 1) {
System.out.println("<< 차트 종류 변경 >>");
System.out.print("차트 종류를 선택하세요(1:bar, 2:line)");
int chartType = keyboard.getInt();
if(chartType ==1) {
// Company객체에 BarChart객체를 전달 (의존하는 객체 전달)
company.setChart(barChart);
} else if(chartType ==2) {
// Company객체에 LineChart객체를 전달 (의존하는 객체 전달)
company.setChart(lineChart);
} //company가 사용하는 차트 종류를 여기서 결정하는 것
} else if(menuNo == 2) {
System.out.println("<< 보고서 출력 >>");
// Company객체의 보고서 출력기능을 실행한다 (내가 전달해준 객체에 대한 drawChart)
company.reporting();
} else if(menuNo == 0) {
System.out.println("### 프로그램을 종료합니다.");
System.exit(1);
}
}
}
}
-----------------------------------
1.차트변경 2.보고서출력 0.종료
-----------------------------------
메뉴 선택: 1
<< 차트 종류 변경 >>
차트 종류를 선택하세요(1:bar, 2:line)1
-----------------------------------
1.차트변경 2.보고서출력 0.종료
-----------------------------------
메뉴 선택: 2
<< 보고서 출력 >>
### BarChart ###
<<분기별 매출 보고서>>
[1분기]■■■■■■■■■■■■■■■■■■■■
[2분기]■■■■■■■
[3분기]■■■
[4분기]■■■■■■■■■■
-----------------------------------
1.차트변경 2.보고서출력 0.종료
-----------------------------------
메뉴 선택: 1
<< 차트 종류 변경 >>
차트 종류를 선택하세요(1:bar, 2:line)2
-----------------------------------
1.차트변경 2.보고서출력 0.종료
-----------------------------------
메뉴 선택: 2
<< 보고서 출력 >>
### LineChart ###
<< 분기별 매출 보고서 >>
[1분기] |
[2분기] |
[3분기] |
[4분기] |
-----------------------------------
1.차트변경 2.보고서출력 0.종료
-----------------------------------
메뉴 선택: 0
### 프로그램을 종료합니다.
<Java API> (Application Programming Interface)
- 자바를 사용해서 애플리케이션을 쉽게 구현할 수 있도록 제공되는 클래스 라이브러리 (=클래스들의 집합)
- 입출력, 네트워크, 자료구조와 같이 애플리케이션 구현에 꼭 필요한 클래스를 미리 구현해 놓은 것
- 자바 API는 JDK(자바개발도구) 설치시 같이 설치된다.
- 이클립스와 같은 통합개발환경에서 프로젝트를 생성하면 Java API를 바로 사용할 수 있도록 프로젝트의 클래스패스에 자동으로 등록시킨다.
* classpath : 자바가상머신이 프로그램을 실행할 때 .class 파일을 찾는 경로를 말한다.
* 대표적인 Java API
- java.lang 패키지 : 자바 애플리케이션 개발에 기본적으로 필요한 라이브러리를 제공하는 패키지
( String, System, Object, Math, StringBuilder, Wrapper 클래스 등을 제공 )
- java.util 패키지 : 자바 애플리케이션 개발에 매우 자주 사용되는 라이브러리를 제공하는 패키지.
( 날짜관련 클래스, 자료구조관련 클래스 등을 제공 )
- java.io 패키지 : 입출력과 관련된 라이브러리를 제공하는 패키지
( 파일, 파일입출력 등 다양한 입출력클래스 제공 )
- java.net 패키지 : 네트워크 관련 라이브러리를 제공하는 패키지
( URL, Socket, ServerSocket 등을 제공 )
- java.text 패키지 : 포맷팅 관련 라이브러리를 제공하는 패키지
(문자열, 숫자, 날짜를 지정된 형식의 문자열로 변환하거나 그 반대 작업을 수행하는 클래스 제공)
- java.time 패키지 : 날짜, 시간관련 라이브버리를 제공하는 패키지
( java8부터 추가 )
<Java API Document>
- Java API에 제공하는 클래스, 인터페이스들에 대한 설명 및 각 클래스나 인터페이스가 제공하는 기능을 설명하는 문서
- Java API 문서는 HTML문서 형식이다
- Java API 문서는 jdk설치경로/bin/javadoc.exe로 생성한다.
- 사용자 정의 프로젝트에서도 javadoc.exe를 사용해서 Java API Documnet를 생성할 수 있다. (직접 API를 만들 수 있음)
오른쪽 - Export - Java - javadoc
'수업내용 > Java' 카테고리의 다른 글
[2022.09.28.수] System 클래스 (0) | 2022.09.29 |
---|---|
[2022.09.27.화] Object 클래스, String 클래스 (0) | 2022.09.28 |
[2022.09.23.금] 추상화, 인터페이스 (0) | 2022.09.24 |
[2022.09.22.목] 강제 형변환, 메소드 재정의와 다형성 (0) | 2022.09.22 |
[2022.09.21.수] 생성자 메소드, 클래스형변환 (0) | 2022.09.21 |