이것저것 공부기록

[부스트코스] 자바로 회계 처리 프로그램 만들기_3 (메소드, 클래스, 인스턴스) 본문

부스트코스 서포터즈 3기

[부스트코스] 자바로 회계 처리 프로그램 만들기_3 (메소드, 클래스, 인스턴스)

채도리 2021. 1. 27. 14:17

*부스트코스 <쉽게 배우는 자바1> 강의를 통해 학습한 내용을 바탕으로 작성한 글입니다.

7. 메소드(Method)

보통 다른 언어에는 함수(Function)라는 것이 존재하는데, 함수는 '어떤 입력값을 주면 어떤 출력값(리턴값)을 돌려주는 것'으로, 들어온 입력값을 가지고 어떤 처리를 하여 리턴값을 돌려주는 블랙박스와 같다.

 

그러나 자바는 클래스가 기본이므로, 클래스를 떠나 존재하는 것은 있을 수 없기 때문에 클래스 내에 존재하는 함수를 메소드라고 부른다. 이전에 사용했었던 Math 클래스의 floor, ceil, PrintWriter 클래스의 write, close 등이 메소드이다.

 

* 함수와 메소드의 가장 큰 차이는 함수는 독립적으로 존재하며, 메소드는 클래스에 종속되어 존재한다는 점이다.

 

즉 메소드는 클래스의 동작을 나타내는 함수로, 쉽게 말해 서로 연관된 코드를 그루핑해서 이름을 붙인 상자라고 할 수 있다.

기본 코드를 가진 AccountingMethodApp이라는 클래스를 생성했다.

public class AccountingMethodApp {
	public static void main(String[] args) {
		double valueOfSupply = 10000.0;
		double vatRate = 0.1;
		double expenseRate = 0.3;
		double vat = valueOfSupply * vatRate;
		double total = valueOfSupply + vat;
		double expense = valueOfSupply * expenseRate;
		double income = valueOfSupply - expense;
		double dividend1 = income * 0.5;
		double dividend2 = income * 0.3;
		double dividend3 = income * 0.2;

		System.out.println("Value of supply : " + valueOfSupply);
		System.out.println("VAT : " + vat);
		System.out.println("Total : " + total);
		System.out.println("Expense : " + expense);
		System.out.println("Income : " + income);
		System.out.println("Dividend 1 : " + dividend1);
		System.out.println("Dividend 2 : " + dividend2);
		System.out.println("Dividend 3 : " + dividend3);
	}
}

지금은 코드가 길지 않아서 보는데 큰 어려움이 없지만, 코드가 늘어나면 늘어날수록 코드를 보기 좋게 정리해야 할 필요가 있다. 또, 똑같은 내용이 여러 번 반복해서 사용될 때 메소드를 작성해서 사용하는 것이 편리하다.

 

먼저 vat 변수의 값을 메소드화해보도록 하자.

double vat = valueOfSupply * vatRate;

 

 

메소드로 만들고 싶은 부분을 블록으로 잡고 마우스 우클릭 - Refactor - Extract Method를 클릭한다.

 

 

메소드의 이름을 getVAT로 지정하고, Access modifier는 public 옵션을 체크, Parameters 아래 세번째 체크박스를 해제한 후 OK를 누르면 이클립스에서 자동으로 메소드를 생성해준다.

 

메소드를 생성하면 vat 변수 부분은 getVAT 메소드를 호출하여 실행하는 코드가 되고,

double vat = getVAT(valueOfSupply, vatRate);

하단에 실제로 메소드 내용을 구현한 코드가 생성된다.

public static double getVAT(double valueOfSupply, double vatRate) {
	return valueOfSupply * vatRate;
}

 

이때 메소드의 호출과 실행 과정을 살펴보도록 하자.

 

변수 vat가 생성될 때 getVAT 메소드가 실행되는데, 이때 메소드의 매개변수로 valueOfSupply, VatRate의 값이 전달된다. 그렇게 전달된 두 값을 곱한 값을 리턴해주므로 리턴값인 valueOfSupply * vatRate 이 vat에 저장되는 것이다.

 

getVAT는 main 메소드의 내부의 변수(지역 변수, Local Variable)인 valueOfSupply와 vatRate를 파라미터로 사용한다. main 메소드의 지역변수인 valueOfSupply와 vatRate가 변수로 사용될 수 있는 범위는 아래 블록으로 잡아놓은 main 메소드 내부뿐이다.

 

 

그렇기 때문에 getVAT 메소드의 파라미터를 지우면 변수에 빨간 줄이 생기며 오류가 발생한 것을 볼 수 있다.

따라서 getVAT 메소드의 파라미터를 없애려면 해당 지역 변수들을 전역 변수(Field)로 바꾸어야 한다.

 

 

전역 변수로 변경하고 싶은 변수 이름 위에서 마우스 우클릭 - Refactor - Convert Local Variable to Field를 클릭하고

 

 

public 옵션을 선택한 후 OK를 클릭한다.

 

public class AccountingMethodApp {
	public static double valueOfSupply;
	public static double vatRate;

	public static void main(String[] args) {
		valueOfSupply = 10000.0;
		vatRate = 0.1;
        
		⋯
	}

	public static double getVAT() {
		return valueOfSupply * vatRate;
	}
}

이제 valueOfSupply와 vatRate는 클래스 내부 어디에서든지 접근할 수 있는 변수가 되었기 때문에 getVAT 메소드의 파라미터를 없애도 오류가 발생하지 않는다.

 

다음은 total 변수를 메소드화해보도록 하겠다.

double total = getTotal(vat);

⋯

public static double getTotal(double vat) {
	return valueOfSupply + vat;
}

이때 getTotal 메소드의 파라미터를 없애려면 아래처럼 수정하면 된다. 이처럼 메소드 안에서 다른 메소드를 호출하는 것도 가능하다.

double vat = getVAT();

⋯

public static double getTotal() {
	return valueOfSupply + getVAT();
}

 

다른 변수들에 대해서도 메소드를 만들고 정리한 전체 코드는 다음과 같다.

public class AccountingMethodApp {
	public static double valueOfSupply;
	public static double vatRate;
	public static double expenseRate;

	public static void main(String[] args) {
		valueOfSupply = 10000.0;
		vatRate = 0.1;
		expenseRate = 0.3;

		print();
	}

	public static double getVAT() {
		return valueOfSupply * vatRate;
	}
	
	public static double getTotal() {
		return valueOfSupply + getVAT();
	}
	
	public static double getExpense() {
		return valueOfSupply * expenseRate;
	}
	
	public static double getIncome() {
		return valueOfSupply - getExpense();
	}

	public static double getDividend1() {
		return getIncome() * 0.5;
	}

	public static double getDividend2() {
		return getIncome() * 0.3;
	}
	
	public static double getDividend3() {
		return getIncome() * 0.2;
	}
	
	public static void print() {
		System.out.println("Value of supply : " + valueOfSupply);
		System.out.println("VAT : " + getVAT());
		System.out.println("Total : " + getTotal());
		System.out.println("Expense : " + getExpense());
		System.out.println("Income : " + getIncome());
		System.out.println("Dividend 1 : " + getDividend1());
		System.out.println("Dividend 2 : " + getDividend2());
		System.out.println("Dividend 3 : " + getDividend3());
	}
}

 

8. 클래스(Class)

클래스와 메소드는 소프트웨어의 구조를 결정하기 때문에 중요하다. 사람 몸에 비유하면 뼈대와 같은 역할을 하는 것.

클래스는 이 포스트에서 정리했듯 연관되어 있는 변수와 메소드의 집합이다.

 

 

먼저 Outline에서(Window - Show View - Outline) 클래스 안에 소속된 멤버들(변수와 메소드)을 확인해보자.

 

만약 지금 만들어 둔 프로그램에 회계 처리 기능 외의 다른 기능을 추가한다면, 비슷한 기능을 위한 것들끼리 분류해두는 것이 좋을 것이다. 그렇지 않고 각기 다른 기능을 위해 만들어진 변수와 메소드들이 한 클래스 내에 모두 존재한다면 프로그램을 만들고 관리하는 데 매우 불편할 것이다. 따라서 이러한 불편함을 해소하기 위해 클래스를 사용할 수 있다.

 

맨 위 상단에 Accounting이라는 클래스를 만들고 변수와 메소드들을 옮긴다.

class Accounting {
	public static double valueOfSupply;
	public static double vatRate;
	public static double expenseRate;
	
	public static double getVAT() {
		return valueOfSupply * vatRate;
	}
	
    	⋯
	
	public static void print() {
		System.out.println("Value of supply : " + valueOfSupply);
		System.out.println("VAT : " + getVAT());
		System.out.println("Total : " + getTotal());
		System.out.println("Expense : " + getExpense());
		System.out.println("Income : " + getIncome());
		System.out.println("Dividend 1 : " + getDividend1());
		System.out.println("Dividend 2 : " + getDividend2());
		System.out.println("Dividend 3 : " + getDividend3());
	}
}

그리고 메인 메소드 안의 변수와 메소드 이름 앞에 Accounting. 을 붙여주어 Accounting 클래스 내의 변수와 메소드라는 것을 알려준다.

public class AccountingClassApp {
	public static void main(String[] args) {
		Accounting.valueOfSupply = 10000.0;
		Accounting.vatRate = 0.1;
		Accounting.expenseRate = 0.3;

		Accounting.print();
	}
}

 

프로그램의 구조만 바뀌었을 뿐, 실행 결과는 동일하다.

 

 

실행 결과

 

작고 간단한 프로그램에서는 이와 같은 과정이 필수적인 것은 아니지만, 프로그램이 거대해졌을 때는 구조를 잘 만들어놓아야 파악하기도 편하고, 유지하고 보수하는 데 유리할 것이다.

 

9. 인스턴스(Instance)

인스턴스는 하나의 클래스를 복제해서, 서로 다른 데이터의 값과 서로 같은 메소드를 가진 복제본을 만드는 것이다.

 

인스턴스는 클래스를  컴퓨터 상에서 실체화한 것이다. (이전 글 참고)

다음과 같이 같은 기능의 메소드를 이용하지만, 내부 상태(변수, 데이터)만 다른 제품이 있다고 가정해보자.

 

1. 상품 a1

Value Of Supply : 10000.0

VatRate : 0.1

expenseRate : 0.3

 

2. 상품 a2

Value Of Supply : 20000.0

VatRate : 0.05

expenseRate : 0.2

 

이럴 경우 각각의 상태에 따라 인스턴스를 생성해서 실행하면 된다. (new 키워드 사용)

* Accounting 클래스의 static 키워드를 모두 지워주어야 함.

public class AccountingClassApp {
	public static void main(String[] args) {
		//Accounting.valueOfSupply = 10000.0;
		//Accounting.vatRate = 0.1;
		//Accounting.expenseRate = 0.3;

		//Accounting.print();
		
		Accounting a1 = new Accounting();
		a1.valueOfSupply = 10000.0;
		a1.vatRate = 0.1;
		a1.expenseRate = 0.3;
		a1.print();
		
		Accounting a2 = new Accounting();
		a2.valueOfSupply = 20000.0;
		a2.vatRate = 0.05;
		a2.expenseRate = 0.2;
		a2.print();
	}
}

 

실행 결과

 

클래스라는 틀 안에서 내부 상태만 다른 각각의 인스턴스들을 만들어 사용한 것이라고 이해하면 되고, 인스턴스는 필요에 따라 얼마든지 만들어 낼 수 있다.

 

마치 속 재료는 다르지만 겉모양은 똑같이 생긴 붕어빵들처럼... 

 

 


 

 

다 함께 배우고 성장하는 부스트코스

부스트코스(boostcourse)는 모두 함께 배우고 성장하는 비영리 SW 온라인 플랫폼입니다.

www.boostcourse.org