다형성 공부하던 도중 예제에서 궁금한 점이 발견되었고, 나는 객체의 선언과 생성에 관하여 약간의 오해가 있었다는 걸 알게 되었다.
Computer com = new Computer();
컴퓨터라는 클래스에서 객체를 하나 생성하였다. 이것을 하나하나 분석해보자
1) Computer com;
내가 만든 클래스인 컴퓨터라는 참조 타입의 변수를 선언하였다(참조 변수). com은 참조 변수 이므로 초기값이 자동으로 null로 설정된다.(지역변수는 꼭 초기화를 거쳐야 한다.) 이제 com은 주소 값이 담길 그릇인 것이다.
2) new Computer();
컴퓨터 클래스의 생성자에 new를 붙여주면 연산자 new에 의해서 Computer클래스의 인스턴스가 메모리 상의 빈 공간에 생성과 함께 이 객체의 주소가 생성된다. 이때 멤버 변수는 각 자료형에 해당하는 기본값으로 초기화된다.
(기본값으로 초기화되는 이유는 생성자 Computer() 때문이다. 생성자는 인스턴스가 생성될 때 호출되는 인스턴스 초기화 메서드이다. 나중에 오버 로딩 등을 배우면 기본값 말고 원하는 값으로 초기화도 가능하다는 것만 알아두고 다음에 여유가 된다면 생성자에 관한 게시물도 다뤄보겠다.)
3) Computer com = new Computer();
대입연산자(=)에 의해서 앞서 생성된 객체의 주소값이 참조변수 com에 저장된다. 이제 com을 이용하여 인스턴스의 멤버 변수에 접근할 수가 있게 되었다.
결론적으로 말하자면 new Computer(); 만으로 객체가 생성된 것이다.
Computer com = new Computer();
위의 형태만이 객체를 만들어서 쓰는 게 아니다.
다음 예제를 살펴보자
이 예제는 다형성에 관한 예제이고 물건을 사고 환불하는 예제이다. 메인 메서드만 가볍게 보고 결과를
import java.util.Vector;
class Product {
int price;
int bonusPoint;
Product(int price) {
this.price = price;
bonusPoint = (int) (price / 10);
}
Product() {
price = 0;
bonusPoint = 0;
}
}
class Tv extends Product {
Tv() {
super(100);
}
public String toString() {
return "Tv";
}
}
class Computer extends Product {
Computer() {
super(200);
}
public String toString() {
return "Computer";
}
}
class Audio extends Product {
Audio() {
super(50);
}
public String toString() {
return "Audio";
}
}
class Buyer {
int money = 1000;
int bonusPoint = 0;
Vector item = new Vector();
void buy(Product p) {
if (money < p.price) {
System.out.println("잔액이 부족하여 물건을 살 수 없습니다.");
}
money -= p.price;
bonusPoint += p.bonusPoint;
item.add(p); // 구입한 제품을 vector에 저장한다
System.out.println(p + "을/를 구입하였습니다.");
}
void refund(Product p) {
if (item.remove(p)) {
money += p.price;
bonusPoint -= p.bonusPoint;
System.out.println(p + "을/를 반품하셨습니다.");
} else {
System.out.println("구입하신 제품중 해당 제품이 없습니다.");
}
}
void summary() {
int sum = 0;
String itemList = "";
if (item.isEmpty()) {
System.out.println("구입하신 제품이 없습니다.");
return;
}
for (int i = 0; i < item.size(); i++) {
Product p = (Product) item.get(i);
sum += p.price;
itemList += (i == 0) ? "" + p : ", " + p;
}
System.out.println("구입하신 물품의 촘 금액은"+sum+ "만원입니다.");
System.out.println("구입하신 제품은 "+ itemList + "입니다.");
}
}
public class PolyArgumentTest03 {
public static void main(String[] args) {
Buyer b = new Buyer();
Tv tv = new Tv();
Computer com = new Computer();
Audio audio = new Audio();
b.buy(tv);
b.buy(com);
b.buy(audio);
b.summary();
System.out.println();
b.refund(com);
b.summary();
}
}
위의 코드는 Tv, Computer, Audio 객체를 생성 후 Buyer객체를 생성하여 각 제품을 구매하는 코드이다.
실행결과
↓↓↓
Tv을/를 구입하였습니다.
Computer을/를 구입하였습니다.
Audio을/를 구입하였습니다.
구입하신 물품의 촘 금액은350만원입니다.
구입하신 제품은 Tv, Computer, Audio입니다.
Computer을/를 반품하셨습니다.
구입하신 물품의 촘 금액은150만원입니다.
구입하신 제품은 Tv, Audio입니다.
그리고 메인 메서드의 객체 생성을 달리해보자
public class PolyArgumentTest03 {
public static void main(String[] args) {
Buyer b = new Buyer();
b.buy(new Tv());
b.buy(new Computer());
b.buy(new Audio());
b.summary();
System.out.println();
b.refund(new Computer());
b.summary();
}
}
실행결과
↓↓↓
Tv을/를 구입하였습니다.
Computer을/를 구입하였습니다.
Audio을/를 구입하였습니다.
구입하신 물품의 촘 금액은350만원입니다.
구입하신 제품은 Tv, Computer, Audio입니다.
Computer을/를 반품하셨습니다.
구입하신 물품의 촘 금액은350만원입니다.
구입하신 제품은 Tv, Audio입니다.
차이점이 보이는가? 바로 computer가 환불되지 않았다. 그 이유는 바로 computer 객체를 두 번 생성하였기 때문이다. 쉽게 말하면 refund에서 new Computer는 우리가 구매하지 않은 새로 생성한 컴퓨터를 환불한 것이다.
그렇다 new Computer() 자체로 이미 주소 값이 할당된 것 즉 인스턴스가 생성된 것이다.
본인은 헷갈렸던 부분이고 객체 생성에 대한 유연함이 생길 수 있었던 좋은 예제였었다. 물론 이런 기초적인 것도 모르냐 할 수 있지만 반대로 나 같은 비전공자들이 코딩을 시작할 땐 너무나도 당연하게 간과할 수 있는 부분 같아서 이렇게 장황하게 글로 남겨본다.
'Java > Java Study' 카테고리의 다른 글
[객체지향] 다형성, Polymorphism - Part2 (참조변수의 형변환) (0) | 2021.05.03 |
---|---|
[객체지향] 다형성, Polymorphism - Part1 (0) | 2021.04.26 |
Call by value (0) | 2021.04.19 |
[객체지향] 클래스, 객체, 인스턴스 (0) | 2021.04.12 |
[객체지향] 객체지향 프로그래밍 (6/2일 추가내용 + 다형성) (0) | 2021.04.12 |