Skip to content

Day 13(21.09.17)

Byeong Gwan Seo edited this page Sep 17, 2021 · 7 revisions

19. 생성자와 메소드 오버로딩(Overload)

(1) 생성자의 오버로딩

외부에서 다양한 데이터가 제공될때, 이를 이용해서 객체를 초기화 하려면 생성자도 다양해질 필요가 있다. 예를 들어, 공장에서 자동차를 찍어낸다고 가정할때, 모델명만 들어오거나, 모델명과 색상이 같이 들어오거나, 색상만 들어온다고 해서 자동차를 안 만들수는 없는 노릇 아닌가? 마찬가지로 생성자가 하나밖에 없다면 다양한 데이터를 활용하기에 어려움이 발생할 수 있다. 생성자의 오버로딩은 이럴때 사용하는 것으로, 매개변수를 달리하는 생성자를 여러개 선언하는 것을 말한다.
다음은 Car 클래스에서의 생성자 오버로드 예시이다.

public class Car {
 Car() {} // 기본 생성자
 Car(String model) {}
 Car(String model, String color){}
 Car(String model, String color, int maxSpeed){}
}

여기서 눈에 띄는 점은, 위에서 말했듯이 생성자마다 매개변수의 종류가 다르다는 점이다. 이 부분은 생성자 오버로드에서 중요한 부분인데, 매개 변수의 순서만 다르고 동일한 경우엔 생성자 오버로딩이라고 볼 수 없다. 즉, 위의 생성자에

 Car (String color, String model){}

이 생성자를 선언한다고 해도 생성자 오버로딩에 해당하지 않고 컴파일 에러가 발생하게 된다. 다음 예시는 위에 예시로 든 생성자 오버로딩을 사용하여 여러개의 객체를 생성하는 프로그램을 작성한 것이다.
Result

car1.company: Hyundai

car2.company: Hyundai
car2.model: Avante

car3.company: Hyundai
car3.model: Grandeur
car3.color: Red

car4.company: Hyundai
car4.model: Sonata
car4.color: Silver
car4.maxSpeed: 200  

위 예시를 통해 Car() 생성자의 오버로딩을 사용함으로써 한 생성자로 다양한 객체를 생성할 수 있는 것을 확인할 수 있다.

(2) 메소드의 오버로딩

생성자와 마찬가지로 메소드의 오버로딩 또한 클래스 내에 같은 이름의 메소드를 여러개 선언하는 것을 뜻한다. 메소드 오버로딩의 조건은 매개 변수의 타입, 갯수 중에서 하나가 달라야 한다. 다음 예시를 확인해보자.

int plus(int x, int y) {
 int result = x + y);
 return result;
}

위 plus() 메소드를 호출하기 위해서는 정수 형태의 값인 매개체가 두 개 필요하다. 하지만 세상만사 덧셈에 정수만 있는 것이 아니다. 실수를 더할 때도 있고, 정수와 실수를 더할 때도 있다. 이럴 경우에 위 plus() 메소드는 사용할 수 없다. 매개변수가 실수를 받지않기 때문이다. 이럴때 메소드 오버로딩을 통해 double 타입을 매개체로 받는 plus() 메소드를 하나 더 생성하면 문제를 해결할 수 있다.

double plus(double x, double y) {
  double result = x + y;
  return result;
}  

이렇게 같은 이름으로 생성된(오버로딩) 메소드를 호출할 경우 JVM은 매개값의 타입을 보고 메소드를 선택한다. 정수 두 개를 입력하면 위의 메소드를, 실수 두개를 입력하면 아래 메소드를 선택하는 것이다. 하지만 이 경우에 x 값에 정수를, y 값에 실수를 입력할 경우에는 어떻게 하냐는 당연한 의문을 가질 수 있다. 하지만, JVM은 아래 plus() 메소드를 선택한다. 매개 변수의 타입이 일치하지 않을 경우엔 자동 타입변환(오토 캐스팅)이 가능한지를 검사하기 떄문이다. 따라서, int 타입은 double 타입으로 변환이 가능하므로 아래의 plus() 메소드가 선택되는 것이다.
다음은 숫자 하나를 받으면 정사각형의 넓이를, 두개를 받으면 직사각형의 넓이를 계산하여 출력하는 프로그램의 예시이다. 정사각형과 직사각형의 영어는 다르지만 메소드 오버로딩의 예시를 들기 위함이니 넘어가도록 하자.
Result

area of square : 100.0
area of rectangle : 40.0

위 예시의 코드에서 확인할 수 있듯, 입력된 매개값은 정수형이지만 실수로 자동변환 되어 실수 값을 뱉어낸다.

20. Static과 Static member

static은 '정적, 고정된'이란 의미이다. static member는 클래스에 고정된 멤버로, 객체를 생성하지 않고서 사용할 수 있는 필드와 메소드를 말한다. 이를 각각 static field(정적 필드), static method(정적 메소드)라고 부른다. 또한 객체에 소속된 멤버가 아니라 클래스에 소속된 멤버이기 때문에 class member라고도 한다.

이 정적 필드와 정적 메소드는 클래스 로더가 클래스를 로딩해서 메소드 메모리 영역에 적재할 때 클래스 별로 관리된다. 때문에 클래스의 로딩이 끝나면 바로 사용할 수 있는 것이다.

(1) static member 선언

정적 필드와 메소드를 선언하는 방법은 각각을 선언할 때 static 키워드를 붙여주면 된다.

public class ClassName {
  //static field
  static classtype field ();

  //static method
  static returntype method() {}

여기서 필드를 객체의 필드로 선언할 것인가, 아니면 정적 필드로 선언할 것인가의 판단 기준은, 객체마다 별개로 가지고 있어야 할 데이터라면 객체의 필드로 선언하고, 객체마다 가지고 있을 필요성이 없는 공용적인 데이터라면 정적 필드로 선언하는 것이 좋다. 예를 들어 파이(3.141592...)의 경우, 언제 어디서나 누가 사용하더라도 같은 변하지 않는 공용적인 데이터이므로 정적 필드로 선언하는 것이 좋다.

메소드 또한 객체 메소드로 선언할 것인가, 정적 메소드로 선언할 것인가의 판단 기준이 있는데, 객체 필드를 이용해서 실행한다면 객체 메소드로, 객체 필드를 사용하지 않는다면 정적 메소드로 선언한다. 예를 들어, 계산기 클래스를 작성한다고 가정할때, 덧셈과 뺄셈의 경우엔 외부에서 주어진 매개값을 가지고 작업을 수행하므로 정적 메소드로 선언하는 것이 좋다. 하지만 계산기의 색깔이나 가격 등을 설정하는 메소드는 객체 메소드로 선언해야 한다.

(2) 정적 멤버의 사용

클래스가 로딩되면 정적 멤버를 바로 사용할 수 있는데, 클래스 이름과 함께 도트(.) 연산자로 접근한다. 예를 들어,

public class Calculator {
 static double pi = 3.141592;
 static int plus(int x, int y) {...}
 static int minus(int x, int y) {...}
}

위와 같이 클래스가 작성되었다면, 정적 필드 pi와 정적 메소드 plus와 minus는 다음과 같이 사용할 수 있다.

double result1 = 10 * 10 * Calculator.pi;
int result2 = Calculator.plus(10,5);
int result3 = Calculator.minus(10,5);

원칙적으로는 위와 같이 클래스 이름을 사용해서 접근해야 하나, 객체를 생성한 뒤, 참조 변수로도 접근이 가능하다. 하지만 가급적이면 클래스 이름으로 접근하도록 하자. 이클립스에서는 애초에 정적 멤버를 참조변수로 접근하면 경고 표시가 뜬다. 다음 예시는 정적 멤버를 사용한 계산기 클래스를 작성한 것이다.
Result

result1: 314.159
result2: 15
result3: 5
---------------------------
result4: 314.159
result5: 15
result6: 5  

위 예시에서 확인할 수 있듯, 참조 변수를 사용해서 정적 멤버에 접근할 수 있으나, 가급적이면 클래스명을 사용해 호출하도록 하자.

Clone this wiki locally