객체지향은 진입장벽이 있는 주제이다보니 아래 코드들을 직접 꼭 쳐보길 바란다.
만약 계산기를 만든다고 치자. 계산기를 보면 대부분의 숫자 키가 동일한 크기와 형태를 갖고 안의 숫자만 다른 것을 볼 수 있다.
public class Main {
public static void main(String[] args) {
// 1 버튼
char btn1Print = '1';
int btn1Space = 1;
String btn1Mode = "DARK";
placeButton(btn1Print, btn1Space, btn1Mode);
// 더하기 버튼
char btnPlusPrint = '+';
int btnPlusSpace = 3;
String btnPlusMode = "DARK";
placeButton(btnPlusPrint, btnPlusSpace, btnPlusMode);
// 클리어 버튼
char btnClearPrint = 'C';
int btnClearSpace = 2;
String btnClearMode = "DARK";
placeButton(btnClearPrint, btnClearSpace, btnClearMode);
}
static void placeButton (char print, int space, String mode) {
System.out.printf(
"표시: %c, 공간: %s, 모드: %s%n",
print, space, mode
);
}
}
위의 코드를 보면 버튼의 내용, 공간, 모드만 지정하는데도 비슷한 종류의 코드가 늘어나는 것을 볼 수 있다. 만약 저런 코드가 계속 길어지는 상황이라면, 중복되는 것을 줄이고 보다 간결하게 코드를 작성할 수는 없을까?
그걸 위해서 클래스를 정의하고, 객체지향 프로그래밍을 해볼 것이다.
📁 ex01☕ Button.javapackage 라인은 지우지 말 것public class Button {
char print;
int space;
String mode;
Button (char print, int space, String mode) {
this.print = print;
this.space = space;
this.mode = mode;
}
void place () {
System.out.printf(
"표시: %c, 공간: %s, 모드: %s%n",
print,space, mode
);
}
}
Main.java 파일과 같은 위치에 생성속성들과 기능들을 정의☕ Main.java Button button1 = new Button('1', 1, "DARK");
Button buttonPlus = new Button('+', 3, "DARK");
Button buttonClear = new Button('C', 2, "DARK");
button1.place();
buttonPlus.place();
buttonClear.place();
객체 object / 인스턴스 instance : 속성(프로퍼티)들과 기능(메소드)들의 묶음 📁 ex02☕ YalcoChicken.java// 본사의 코드
public class YalcoChicken {
// 인스턴스가 가질 필드(field)들
int no;
String name;
// 인스턴스가 가질 메소드 - 💡 static을 붙이지 않음
String intro () {
// no와 name 앞에 this를 붙인 것과 같음
return "안녕하세요, %d호 %s점입니다."
.formatted(no, name);
}
}
public 클래스일 시)본사는 매장들이 각각 어떤 정보를 갖고 있을지(필드), 그리고 그 매장들이 어떤 역할을 하도록 시킬지(메소드)를 지정한다. 위 코드에서 필드는 각 매장이 갖고 있을 정보라고 생각하면 된다. 또한 위 코드에서 메소드는 각 매장들이 해야할일, 예를 들면 손님 응대나 주방 관리와 같은 것들이라고 생각하면 된다.
이제 위에서 만든 클래스를 Main클래스에서 인스턴스로 만들어서 사용해보자.
즉 본사의 틀을 바탕으로 지점매장을 내는 것이라고 생각하면 된다.
// 본사 소속의 매장을 내는 코드
YalcoChicken store1 = new YalcoChicken();
store1.no = 3; // 🔴
store1.name = "판교";
YalcoChicken store2 = new YalcoChicken();
store2.no = 17;
store2.name = "강남";
// 인스턴스의 필드들에 접근
int store1No = store1.no;
String store2Name = store2.name;
// 인스턴스의 메소드 호출
String store1Intro = store1.intro();
String store2Intro = store2.intro();
위의 코드의
YalcoChicken store1 = new YalcoChicken();
이 부분을 보면 YalcoChicken 으로 정의한 클래스가 Main 클래스 안에서 자료형처럼 사용되는 것을 알 수 있다. store1 은 인스턴스의 변수명이다. 위 코드의 포멧을 반드시 외우고 있어야 한다.
다시 Main.java 의 코드를 살펴보면 인스턴스가 가진 속성들을
store1.no = 3;
store1.name = "판교";
이런식으로 . 을 붙여서 값을 넣어줄 수도 있고, 또한
// 인스턴스의 필드들에 접근
int store1No = store1.no;
String store2Name = store2.name;
이런식으로 그 값들을 빼서 다른 변수에다가 넣어줄 수도 있는 것이다.
또한
// 인스턴스의 메소드 호출
String store1Intro = store1.intro();
String store2Intro = store2.intro();
이런식으로 인스턴스의 메소드를 호출할 수도 있다.
📁 ex03☕ YalcoChicken.javapublic class YalcoChicken {
int no;
String name;
// ⭐ 생성자(constructor) : 인스턴스를 만드는 메소드
// ⭐ this : 생성될 인스턴스를 가리킴
YalcoChicken (int no, String name) {
this.no = no;
this.name = name;
}
String intro () {
// String name = "몽고반"; // 주석해제 시 name 대체
return "안녕하세요, %d호 %s점입니다." // 🔴
.formatted(no, name);
}
}
위 코드를 보면 생성자가 존재하는데, 보통 필드와 메소드 사이에 들어간다. 클래스명이 그대로 들어가고 괄호 안에 매개변수가 존재하는 것으로 보면 일종의 메소드이다. 클래스와 똑같은 이름이 붙여지는데, 정확하게는 이름이 아니라 반환값이다. 즉 해당 클래스가 반환값으로 되어 있고, 메소드명이 따로 없는 이런 메소드를 생성자라고 한다. 이런 생성자는 인스턴스를 만드는, 즉 매장을 내는 메소드라고 생각하면 된다. 본사에서 이 브랜드의 매장을 내려면 이와 같이 내라 이런거라고 생각하면 된다.
☕ Main.javapublic class Main {
public static void main(String arg[]) {
// 클래스로 인스턴스를 생성 - 💡 new 연산자 + 생성자 호출
// 본사의 방침대로 매장을 내는 것
YalcoChicken store1 = new YalcoChicken(3, "판교");
YalcoChicken store2 = new YalcoChicken(17, "강남");
YalcoChicken store3 = new YalcoChicken(24, "제주");
String[] intros = {store1.intro(), store2.intro(), store3.intro()};
}
}
return 을 명시하지 않음 - 해당 클래스 타입의 인스턴스 반환new 연산자와 함께 사용되어 인스턴스를 반환.class 파일에서 확인 가능command + N생성자 선택name 과 price 선택ex02 의 컴파일된 파일 YalcoChicken.class 살펴볼 것this - 만들어질 인스턴스를 가리킴intro 메소드 브레이크포인트에서 this 항목 확인no와 name 에 this 를 붙인 것과 같음 this 의 필드를 가리킴this 를 붙여 구분this 를 빼고 실행해 볼 것intro 에서 주석 해제해 볼 것, this 를 사용하여 다시 해 볼 것