Java - 객체지향 프로그래밍(1) 클래스 기초

민찬홍·2023년 9월 14일

Java

목록 보기
21/31
post-thumbnail

🧩 클래스 기초

객체지향은 진입장벽이 있는 주제이다보니 아래 코드들을 직접 꼭 쳐보길 바란다.

🧩 클래스/ 객체 없이 프로그래밍을 한다면?

만약 계산기를 만든다고 치자. 계산기를 보면 대부분의 숫자 키가 동일한 크기와 형태를 갖고 안의 숫자만 다른 것을 볼 수 있다.

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.java
  • 파일 생성시 작성된 최상단의 package 라인은 지우지 말 것
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 파일과 같은 위치에 생성
  • 클래스 class : 각 버튼이 갖고 있을 속성들과 기능들을 정의
☕ 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클래스에서 인스턴스로 만들어서 사용해보자.
즉 본사의 틀을 바탕으로 지점매장을 내는 것이라고 생각하면 된다.

☕ Main.java
		//  본사 소속의 매장을 내는 코드
		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.java
public 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.java
public 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
    • 생성자 선택
    • nameprice 선택
  • 🌟 생성자를 작성하지 않는다고 생성자가 없는 것이 아님
    • ex02 의 컴파일된 파일 YalcoChicken.class 살펴볼 것

🌟 this - 만들어질 인스턴스를 가리킴

  • intro 메소드 브레이크포인트에서 this 항목 확인
    • nonamethis 를 붙인 것과 같음
  • 메소드 내에서 같은 이름의 변수나 인자가 없다는 식별자는 this 의 필드를 가리킴
  • 같은 이름의 변수나 인자가 있다면 덮어씌워짐
    • 필드의 this 를 붙여 구분
    • 생성자에서 this 를 빼고 실행해 볼 것
    • intro 에서 주석 해제해 볼 것, this 를 사용하여 다시 해 볼 것
profile
백엔드 개발자를 꿈꿉니다

0개의 댓글