본문 바로가기
개발언어/JAVA

Java 개발을 위한 클래스(Class)

by 이엘리야 2023. 8. 13.

안녕하세요.

이번 시간에는 클래스(Class)에 대해서 알아보겠습니다.

앞선 포스팅에서 클래스 메소드 등 여러 어려운 말이 나왔을 텐데

이번 포스팅에 전부 정리해 보도록하겠습니다.

 

우선 클래스를 간단하게 정의해 보면

"객체를 정의한 설계도"로 생각하시면 됩니다.

즉 변수 + 메소드이며

객체는

'상태'와 '행동'을 가지는 대상

예를 들면 실세계에 있는 모든 것이 객체가 될 수 있습니다

 

클래스는

객체의 '상태'를 '변수'로

객체의 '행동'을 '메소드'로 정의한 것입니다.

즉 이전 포스팅에서 만든

StringEquals 자체가 클래스가 됩니다.

 

메소드는 

특별한 기능을 수행한 코드의 모음이며

일반적으로, 입력값을 전달받아, 특정 연산을 수행한 후

연산의 결과를 출력하는 구조를 가지고 있습니다.

전달받는 값이 없을 수도 있고, 출력하는 값이 없을 수도 있습니다.

메소드의 용어를 잠깐 정리해 보자면

정의, 호출, 인수(인자), 매개변수, 반환값이 있으며

정의는 새로운 사용자 메소드를 만드는 것

호출은 정의된 메소드를 실행 요청하는 것

인수(인자)는 메소드에 전달해 주는 입력값 (argument)

매개변수는 입력값을 전달받는 변수 (parameter)

반환값은 함수가 출력하는 값 (return)

을 말합니다.

 

메소드를 잠시 정의해 보자면

특정 기능을 수행할 코드 모음이라고 말했는데

형태를 보게 되면

접근지정자 (static) 반환타입 메소드명(매개변수) { }

이렇게 구성되게 됩니다.

public static void func(int a, int b) {

실행문;

}

메소드에 void가 있으면 retrun을 입력해 주지 않아도 되며

void가 아니라 int String 등 반환타입 있으면 무조건 return으로 값을 반환해 줘야 합니다.

return(값)은

메소드를 종료함과 동시에

값을 메소드를 호출한 곳으로 반환해 주는 역할입니다.

 

클래스에 대해 잠시 예를 들어보면

포켓몬이라는 클래스가 있다고 가정해 봅시다.

public class Poketmon {
	// 변수
	private String name;
	private String type;
	private int energy;
    
    // 메소드
	public void attackA() {...}
	public void attackB() {...}
}

즉 포켓몬이라는 객체의 상태(이름, 타입, 에너지)를 변수

행동(공격 A, 공격 B)라고 생각해 볼 수 있습니다.

 

인스턴스(Instance) 란

"클래스의 정의대로 생성된 실체"를 의미하며

객체 생성 = 인스턴스 생성입니다.

클래스를 실제 사용할 수 있도록 변수로 선언한 것이며

클래스의 변수/메소드는 객체(인스턴스)로 생성해야 메모리에 할당되고 사용할 수 있습니다.

키워드는 new입니다.

여기서 보게 되면 앞에 String에서 사용한 new String을 기억하실 텐데

맞습니다. String은 클래스이기 때문에 new String으로 객체를 생성해서

각각의 값을 정해줘야 하는데 그냥 String a 이렇게 선언해도 무방한 이유는

앞서 설명한 것과 같이 String a라고 선언하게 되면 주소값을 가지고 그 주소값이

본래의 값을 가지게 됩니다.

즉 그냥 String a라고 선언하게 된다면 리터럴

String a = new String()이라고 하면 객체 생성이 됩니다.

 

다시 돌아와서 객체 생성을 위해선

클래스타입 객체명 = new 클래스명();

Poketmon poketmon = new Poketmon();

이렇게 객체 생성을 해야 합니다.

생성을 한 후에 그 클래스의 기능을 사용해야 하는데

그때 사용하는 게 접근 연산자(.)입니다

접근 연산자는 생성된 객체의 변수와 메소드에 접근하는 연산자를 의미하며

사용방법은 아래와 같습니다.

	Poketmon poketmon = new Poketmon();
	poketmon.setName("피카츄");
	System.out.println(poketmon.getName());

이렇게 접근연산자로 생성한 객체에 접근하여 값을 가져올 수 있고 새로운 값을 할당할 수 있습니다.

 

간단하게 정리해 보자면

클래스 : 객체를 정의한 설계도

인스턴스(객체) : 클래스를 실제로 사용할 수 있도록 선언한 것

    - 변수(멤버변수) : 객체의 상태(속성)

    - 메소드(멤버함수) : 객체의 행동(기능)

이렇게 볼 수 있습니다.

 

A클래스의 메인메소드에서 B 클래스의 객체를 선언하고 객체의 기능을 사용하기 위해선

B 클래스의 생성자가 있어야 하는데

여기서 생성자(Constructor)란

인스턴스 변수를 초기화하기 위해, 객체 생성 시(new) 호출되는 메소드를 뜻합니다.

클래스명과 생성자명이 동일하며

리턴 타입을 정의하지 않습니다.

또한 생성자는 상속되지 않으며

기본 생성자를 정의하지 않으면, 컴파일러가 자동으로 생성해 주게 됩니다.

하지만 매개변수가 있는 생성자를 정의하면, 더 이상 컴파일러가 기본 생성자를

자동 생성하지 않습니다.

즉 예를 들어보자면 아까 만든 Poketmon 클래스의 생성자를 만들게 되면

이런 식으로 생성자가 만들어지게 됩니다.

여기에 매개변수가 있는 생성자를 추가하게 되면

이런 형식이 되는 것입니다.

 

여기서 this와 this()가 있는데

this는 this.XXX

this()는 this(X, X, X)

 형식으로 사용되며 

this는

현재 객체 자신을 가리키는 레퍼런스로

객체의 멤버(변수/메소드)에 접근할 때 사용하며

멤버 변수의 이름과 메소드의 매개변수의 이름이 같은 때, 이를 구분해 주기 위해 사용합니다.

(멤버변수) - this.name

(매개변수) - name

 

this()는

생성자의 다른 생성자를 호출하는 메소드이며

this()는 반드시 생성자 코드에서만 호출할 수 있고,

반드시 같은 클래스 내 다른 생성자를 호출할 때 사용하여야 하며,

반드시 생성자의 첫 번째 문장이 되어야 합니다.

 

즉 this()는 이런 식으로 사용이 되며

this는

이렇게 사용됩니다.

 

예제코드로 한번 알아보겠습니다.

우선 Poketmon 클래스와

main 메소드를 가지고 있는 Jiwoo 클래스를 만들어보겠습니다.

 

우선 Poketmon 클래스에서 변수를 선언해 줍니다.

이렇게 private를 걸게 되면 외부에서는 호출을 할 수 없게 됩니다.

즉 클래스 내에서만 호출과 선언이 가능하게 됩니다.

 

그다음 생성자를 만들어주겠습니다.

이클립스에서는 생성자를 자동으로 만들어 주는 기능을 가지고 있는데

그 기능을 사용하면 편합니다!

단축키는 Alt + Shift + S이며 

단축키를 누르게 되면 이러한 창이 뜨는데

Generate Constructor using Fields를 눌러 주시고

 

여기서 체크박스를 전부 해제하신 다음에 Generate를 눌러주시면

매개변수가 없는 기본 생성자가 생성됩니다.

 

저희는 아직 상속받고 외부에서 값을 받아오지 않을 거 기 때문에 

체크를 해제하고 진행하겠습니다.

 

여기까지 진행하셨다면

다음엔 main 메소드에서 private로 접근지정된 name, type, energy를

사용하기 위해 값을 받아오고 저장하는 getter, setter를 

생성해 보겠습니다.

 

아까와 동일한 단축키로

이번엔 Generate Getters and Setters... 를 눌러

체크 박스를 전부 체크해 주신 다음에

Generate를 눌러주세요.

그럼 위의 그림과 같이 생성되셨을 건데

여기서 잠깐 getter와 setter에 대해 설명하고 넘어가겠습니다.

 

Setter는

setName, setType, setEnergy가 있는데

직접적인 접근을 막고 외부에서 들어오는 값을 메소드를 통해 전달하는 기능을 합니다.

 

Getter는

getName, getType, getEnergy가 있는데

받아온 값을 가공 후 다시 외부로 전달하는 역할을 하게 됩니다.

이번 예제에서는 이름 타입 에너지만 받아서 전달하지만

실제로는 값을 받아와서 연산 후 리턴해주는 방법이 있습니다.

 

이렇게 getter와 setter를 선언해 줬으면 이제

메소드를 만들어 줄 겁니다.

포켓몬은 이름 타입 에너지뿐 아니라 공격하는 기능도 있기에

이런 식으로 반환타입이 없는 메소드를 작성해 줍니다.

 

그다음 Jiwoo 클래스로 이동하여

main 메소드 안에

위와 같은 코드를 작성해 주시면 됩니다.

여기서 저희는 따로 이름과 타입 에너지에 해당하는

name type energy라는 변수를 선언해 주지 않았습니다.

Poketmon poketmon = new Poketmon()이라는 새로운 객체를 만들어주고

poketmon이라는 변수명으로 Poketmon 클래스 안에 있는

Name, Type, Enetgy에 값을 담아 전달해 줄 겁니다.

전달하는 방법은 아까 getter, setter를 이용해 전달을 하게 되는데

setName, setType, setEnergy로 값을 담아 setter를 통해 전달합니다.

그리고

밑에 출력을 위한 getName, getType, getEnergy로 getter를 통해 값을 받아와서

출력을 진행하게 됩니다.

 

여기서 attackA와 B는 퍼블릭 타입으로 공개되어 있기에

객체 생성만으로도 사용할 수 있습니다.

결과 값을 한번 볼까요?

입력된 값이 잘 출력되는 것을 확인할 수 있습니다.

 

또한 여기서는 Jiwoo 클래스에서 직접 setName으로 값을 담아서 getName으로 출력했지만

Poketmon 클래스에서 직접 담아서 출력하는 방법도 있습니다.

방법 하나만 살펴보고 마무리하도록 하겠습니다.

Poketmon 클래스로 이동 후 

Generate Constructor using Fields... 를 눌러주세요.

그다음 기본 생성자 생성을 위해 체크를 해제했던 것과는 달리

이번에는 전체를 체크해 주시고 Generate를 눌러주세요.

그럼 이렇게 매개변수가 담긴 생성자가 생성된 것을 볼 수 있습니다.

위치는 상관없으나 되도록이면 기본 생성자 아래로 배치해 주세요!

 

이번엔 아까 설명드린 this() 메소드를 사용해 보겠습니다.

기본 생성자에 this("피카츄", "전기", 100)라고 작성해 주세요.

이렇게 되면 아래 매개변수의

name, type, energy에

기본 생성자가 호출될 때 자동으로 값이 들어가게 됩니다.

 

이 상태로

다시 Jiwoo 클래스로 돌아와서

해당 부분을 주석 처리 후

실행해 보시면

아까와 같은 값을 출력하는 걸 볼 수 있습니다.

이런 식으로 값을 전달하고 받아서 처리하는 방법이 있으며

클래스에서 이러한 기능이 이루어집니다.

 

약간의 예제를 통해 설명을 드렸는데

이해하셨는지 모르겠습니다.

 

이해가 안 되시거나 잘못된 점이 있으면

댓글을 통해 말씀해 주시기 바랍니다!

 

다음 포스팅은 클래스 상속에 대해 다뤄보겠습니다.

 

감사합니다 :)