241017 클래스 정리하기

물고기가자라면어그로·2024년 10월 17일
0

Java 공부를 시작하고 클래스의 개념을 이해하는 것은 정말 고비였는데, 공부를 하면서도 사실 이해가 완전히 되지 않아서 계속 TIL 쓰기를 주저하고 있었다. 물론 스스로 정리를 하며 이해할 수도 있었지만 이미 강의자료를 여러차례 읽어도 이해가 되지 않던 부분이 많았기 때문에 망설임이 내 발목을 잡고 있었다. 튜터님들의 도움도 받고 직접 코드를 작성도 해보며 조금씩 나아지고 있었는데 오늘 보충강의를 듣고 질의 끝에 머리가 시원해지는 부분이 있어 드디어 클래스에 대해 정리해보기로 다짐했다.

클래스

클래스는 객체를 생성하기 위한 설계도라고 할 수 있다.
클래스는 필드, 생성자, 메서드로 이루어져있다.

  • 필드(attribute) : 객체의 속성들
  • 생성자 : 객체가 생성되는 방식(+생성 시 실행/선언하는 것)
  • 메서드 : 객체가 가질 수 있는 기능들

우리는 이 클래스로부터 여러 객체를 생성할 수 있다.
이 때, 객체들은 서로 다른 값의 필드를 가지게 될 수 있다.

객체를 생성하는 법

클래스를 사용할 다른 클래스의 메인 메서드에 다음과 같은 방식으로 클래스를 인스턴스화 시킬 수 있다.

클래스명 객체명 = new 클래스명(매개변수1, 매개변수2, ...)

혹은 배열 형태의 객체를 생성 후, 새로운 객체들을 생성하여 이 객체 배열 안에 넣어줄 수도 있다.

클래스명[] 객체배열명 = new 클래스명[배열크기];

클래스명 객체명1 = new 클래스명 ( 매개변수1, 매개변수2, ... );
객체배열명[0] = 객체명1;

클래스명 객체명2 = new 클래스명 ( 매개변수1, 매개변수2, ... );
객체배열명[1] = 객체명2;
.
.

클래스가 객체화 될 때 요구하는 매개변수가 있을 수 있다.
이는 클래스의 생성자에서 지정하는 것이다.

그렇다면 클래스를 만드는 방법부터 예시를 들어 설명해보겠다.

클래스 생성하기

예를 들어 "롤 구단"에 대한 클래스를 만든다고 생각을 해보자.
클래스의 이름LolTeam 으로 하겠다.
클래스의 필드(속성)은 감독, 포지션 별 선수들(, 정글, 미드, 원딜, 서폿), 연간예산이 있다고 치자.
그리고 팀의 기능(행위)는 롤 대회에서 경기를 치루는 것이니 메서드는 다음 두 개를 설정해보겠다.

  • 롤드컵에 나가서 이길 경우, 연간예산이 상승하고 선수들이 모두 그대로 잔류하는(변화x) 메서드
  • 롤드컵에 나가서 질 경우, 연간예산이 하락하고 선수들의 계약이 끝나는 메서드

그럼 다음과 같은 클래스를 생성할 수 있게 된다.

public class LolTeam{

    // 필드 : 속성
    String headCoach;
    String top;
    String jg;
    String mid;
    String adc;
    String sup;
    int budget = 0; //억단위라고 생각하자

    //생성자 : 클래스 생성 양식 및 설정
    public LolTeam (String headCoach, String top, String jg, String mid, String adc, String sup) {
        public this.headCoach = headCoach;
        public this.top = top;
        public this.jg = jg;
        public this.mid = mid;
        public this.adc = adc;
        public this.sup = sup;
        public budget = 100;
    }

    //메서드 : 기능(행위)
    public int worldsWin(int year) {
        budget+=100;
        return budget;
    }

    public int worldsLose(int year) {
        budget-=50;
        top=null;
        jg=null;
        mid=null;
        adc=null;
        sup=null;
        return budget; 
    }
}

괜히 길어지고 정리용이라기엔 깔끔하지도 않지만 좋아하는 걸로 예시를 들려고 하면 이렇게 된다.

아무튼 차근차근 뜯어보면 이렇게 된다.

1. 클래스선언

접근제어자 class 클래스명{}

예시에서는 모두에게 접근이 허용된(public) 클래스 "LolTeam"을 선언하였다.

2. 필드 정의

타입 필드명;

budget처럼 필드의 초기값을 설정해줄 수도 있다.

3. 생성자 선언

접근제어자 클래스명 (매개변수1, 매개변수2, ...) {
   // 초기설정내용;
}

이 때, 소괄호 안에 들어가는 매개변수들은 객체를 생성할 때 입력해줘야하는 값들이다.
이들을 입력해줘야만 클래스를 생성할 수 있다.
(생성자 단계에서 소괄호를 비워두면 매개변수 없이 객체가 생성가능하다.)
이 입력값들을 미리 선언한 필드에 넣기 위해서 this.를 사용해준다.
this는 지금 작성중인 클래스의 주소를 불러와준다.

즉, 예시에서

    public LolTeam (String headCoach, String top, String jg, String mid, String adc, String sup) {
        this.headCoach = headCoach;
        this.top = top;
        this.jg = jg;
        this.mid = mid;
        this.adc = adc;
        this.sup = sup;
        budget = 100;
    }

this.뒤에 붙은 headCoach필드의 headCoach를 의미하고
뒤의 등호로 이어진 headCoach매개변수의 headCoach를 의미한다.

budget = 100처럼 생성자에서 클래스 생성 시의 값을 선언해주는 것도 가능하다.

4. 메서드 선언

접근제어자 반환할 값의 데이터타입 메서드명 (매개변수1, 매개변수2 ...) {
  // 메서드 내용
  return 반환할 값
}

이 때, return으로 반환할 값이 없다면 데이터타입에 void를 적어주면 된다.

인스턴스 멤버와 클래스 멤버

이 개념이 이해가 되지 않아 한참 고생했던 기억이 있다.
헷갈렸던 이유는 바로 멤버와 클래스의 개념을 혼동하고 있었기 때문인데
멤버필드와 메서드를 묶어 말하는 것이고 클래스의 구성 역시 필드, 메서드, 생성자로 이루어져있기 때문이다.

멤버 = 필드 + 메서드
클래스 = 객체를 만들기 위한 설계도

클래스의 구성이 필드, 메서드, 생성자이기 때문에 멤버 역시 필드나 메서드의 형태로 클래스의 안에 들어갈 수 있다.

멤버는 선언하는 방법에 따라 인스턴스 멤버클래스 멤버로 구분지을 수 있는데,

  • 인스턴스 멤버객체 생성 후에 사용할 수 있는 필드와 메서드,
  • 클래스 멤버객체 생성 없이도 사용할 수 있는 필드와 메서드이다.

위에서 설명한 필드와 메서드는 전부 인스턴스 멤버였다.
객체의 인스턴스 필드들은 각각의 인스턴스마다 고유한 값을 가질 수 있다.

그러나 클래스 멤버고정적으로 존재하는 필드와 메서드로, 모든 인스턴스가 같은 값을 가지고 있을 때 사용하는 것이 좋다.
static 키워드를 사용하여 선언할 수 있으며, 인스턴스1에서 클래스 멤버를 변경할 경우 인스턴스2에서도 자동으로 같은 값으로 바뀌게 된다.

예시를 들어보자면, 위의 LolTeam에서 팀의 국적이 모두 한국 팀인 객체들만 만들 예정이라면 LolTeam의 필드에 국적이라는 클래스 필드를 선언해줄 수 있다.

public static String country = "Korea";

이렇게 되면 생성되는 모든 팀들은 Korea를 국적으로 가지게 되며, 혹여 한 팀의 국적을 중국으로 변경시킨다면 다른 팀들의 국적도 모두 공유되고 있기때문에 함께 중국으로 바뀌게 될 것이다.

클래스 멤버를 사용할 때 주의할 점은 다음과 같다.

  • 클래스 멤버로 선언된 메서드는 인스턴스 멤버를 사용할 수 X
  • 인스턴스 멤버는 클래스 멤버를 사용할 수 O

    클래스멤버는 객체 생성없이 바로 사용가능한데 인스턴스 멤버는 객체가 생성되어야만 존재할 수 있기 때문이다.

Final 필드와 상수

final 필드

final은 '최종적'이라는 의미를 가지고 있다.
따라서 final 필드는 초기값이 저장되면 절대로 수정할 수 없다.
(초기값을 반드시 지정해주어야한다.)

final 필드타입 필드명 = 초기값;

상수

상수는 값이 반드시 한 개이며 불변의 값을 의미한다.
따라서 인스턴스마다 상수를 저장할 필요가 없다.
final 앞에 static을 붙이는 방법으로 선언할 수 있다.

static fianl 필드타입 필드명 = 초기값;

수정할 수 없는 클래스 멤버와도 같다.

접근제어자

그렇다면 위에서 계속 나온 이 접근제어자는 무엇일까?
접근제어자는 외부에서 접근할 수 있는 제한을 걸어주는 것이다.

  • public : 모두가 사용가능
  • protected : 같은 패키지 내, 다른 패키지의 자손 클래스에서도 접근이 가능
  • default : 같은 패키지 내에서만 접근 가능
  • private : 같은 클래스 내에서만 접근 가능

접근제어자를 설정하지 않은 경우에는 일반적으로 default 값이 지정된다.

Getter와 Setter

접근이 제한된 파일을 읽어오거나 수정하고 싶을 때 Getter와 Setter 메서드를 사용한다.
예를 들어 privatedefault의 필드를 읽어오고 싶을 때 Getter을 사용하고 수정하고 싶을 때는 Setter을 사용하는 것이다.

사용방법은 필드의 이름앞에 get / set을 쓰고 필드의 첫문자를 대문자로 바꾸어주는 것이다.

  • get+필드명(첫글자 대문자)
    ex) String color -> String getColor
  • set+필드명(첫글자 대문자)
    ex) int price -> int setPrice

0개의 댓글