Java - 기본기

15. 객체 지향 언어란? 클래스와 객체(활용편) : 클래스와 객체 활용한 게임 만들기

TerianP 2021. 10. 19.
728x90

1. 하나의 소스파일에 여러 클래스 작성하기

  • 자바 소스 파일 안에는 2개 이상의 클래스를 넣을 수 있음.
  • 이때 소스 파일 명과 public class의 "클래스명" 이 일치하여야 한다.
  • 단!! public class 가 없는 경우 소스 파일 이름은 해당 소스 파일 내 어떤 클래스의 이름으로 해도 무방하다.
비고 자바 소스 파일 명 자바 클래스 명 설명
올바른 예 Hello2.java public class Hello2{}
class Hello3
public class 가 있는 경우 소스파일의 이름은 반드시 public class 와 일치해야한다.
Hello3.java class Hello2{}
class Hello3{}
public class가 하나도 없는 경우 소스파일의 이름은 어떤 클래스명으로해도 무방하다.
잘못된 예 Hello2.java public class Hello2{}
public class Hello3{}
하나의 소스파일에 둘 이상의 public class 가 존재하면 안된다.
Hello3.java public class Hello2{}
class Hello3{}
소스파일의 이름이 public class 의 이름과 일치하지 않는다. 즉 Hello3.java -> Hello.2java 로 바꾸어야 한다.
hello2.java public class Hello2{}
class Hello3{}
소스파일의 이름과 public class 클래스 명은 완전히 일치해야 한다. 이는 대소문자도 구분을 한다는 의미이며 hello2.java -> Hello3.java 로 바꾸어야한다.

 

2. 객체의 생성과 사용

1) 객체의 생성

  • 객체의 생성 : 사실 객체의 생성은 처음 해보는 것이 아니라 아마 엄~~청 많이 해봤을 것이다. 간단하게 Scanner 를 사용해서 입력을 받는 것부터 객체를 생성하는 것이였으니...
// 원래는
클래스명 변수명; // 클래스의 객체를 참조하기 위한 참조변수 선언
변수명 = new 클래스명(); // 객체 생성 후 객체 주소를 참조변수에 저장

// 한번에 묶어서
클래스명 변수명 = new 클래스명();


// 예시를 보자면
Scanner scan;
scan = new Scanner(System.in);

=> 묶어서 =>
Scanner scan = new Scanner(System.in);

여기서!! 중요한 부분은 참조 변수를 하나 생성하고, 그 참조 변수에 생성한 객체 주소를 저장한다고 생각하면 된다.

 

2) 객체의 사용

  • 여기서 멤버 변수란 클래스 내 변수를 의미
  • TV 클래스는 멤버 변수 4개, 매서드 3개로 구성됨
TV 클래스를 예로 들자면,

// 클래스 생성
class Tv{
	// 속성 정의
	String color;  // 멤버 변수1
	boolean power; // 멤버 변수2
	int channel; // 멤버 변수3
	String display; // 멤버 변수4

	// 기능 정의
	void power() {
		power = !power;
	}

	void channelUp(){
		channel++;
	}

	void channelDown() {
		channel--;
	}
}

// 객체 생성 & 사용
Tv t = new Tv(); // Tv 클래스의 객체를 생성하여 참조변수 t에 객체 주조 저장

t.color = "red"; // TV 인스턴스의 멤버변수 color 의 값을 red 로 저장
t.display = "UHD"; // TV 인스턴스의 멤버변수 display 의 값을 UHD 로 저장

t.channelUp(); // TV 인스턴스의 메서드 channelUp() 메서드를 호출한다. 해당 메소드의 기능은 channel 의 값을 +1 하는 것

 

  • 2개의 TV 클래스 인스턴스 생성
Tv tv_1 = new Tv();

tv_1.color = "red";
tv_1.channel = 32;
tv_1.display = "UHD";
		
System.out.println("A사 TV 색깔 : "+tv_s.color);
System.out.println("A사 TV 해상도 : "+tv_s.display);
		
Tv tv_2 = new Tv();
tv_2.color = "Blue";
tv_2.channel = 33;
tv_2.display = "QHD";
		
System.out.println("B사 TV 색깔 : "+tv_l.color);
System.out.println("B사 TV 해상도 : "+tv_l.display);


// 출력 
// 객체 tv_1 과 tv_2 는 서로 다른 주소값을 갖음. 이는 tv_1 참조변수에 값을 넣었을 때와
// tv_2 참조변수에 값을 넣었을 때 서로 다른 출력 결과를 갖는 것을 통해 확인 가능 
A사 TV 색깔 : red
A사 TV 해상도 : UHD
A사 인스턴스 객체 주소값 = day21.Tv@282ba1e

B사 TV 색깔 : Blue
B사 TV 해상도 : QHD
B사 인스턴스 객체 주소값 = day21.Tv@13b6d03
  • 이때 아래와 같이 고쳤을 경우 GC, 일명 가비지 컬렉터가 출동하여 사용할 수 없는(사용되지 않는?) 객체들을 메모리에서 제거하여 불필요하게 메모리가 낭비되는 일이 없도록 함
Tv tv_1 = new Tv();

tv_1.color = "red";
tv_1.channel = 32;
tv_1.display = "UHD";
		
System.out.println("A사 TV 색깔 : "+tv_s.color);
System.out.println("A사 TV 해상도 : "+tv_s.display);
		
Tv tv_2 = new Tv();

tv_2 = tv_1; 
// 변수 tv_1 값을 tv_2 에 저장.
// 즉 tv_2 가 tv_1 과 더 이상 서로다른 주소값을 갖는 것이 아니라 서로 동일한 주소값과 내용을 갖게됨

tv_2.color = "Blue";
tv_2.channel = 33;
tv_2.display = "QHD";
		
System.out.println("B사 TV 색깔 : "+tv_l.color);
System.out.println("B사 TV 해상도 : "+tv_l.display);
  • tv_2 = tv_1 을 넣은 순간부터 기존의 tv_2 가 가졌던 주소 값은 더 이상 사용할 수 없는 주소값이기 때문에 GC(가비지 컬렉터) 가 등장!! 필요없어진 주소값을 메모리로부터 삭제!!
  • GC 는 자동으로 출현하여 자신의 기능을 처리하기 때문에 사람이 직접 손 댈 필요가 없다는 장점이 있다.

⇒ 여기서 한 번 짚고 넘어가자면 하나의 인스턴스를 여러 개의 참조 변수가 가리키는 것은 가능하다.

Tv t1 = new Tv();
Tv t2 = new Tv();
t2 = t1; // t2 와 t1 은 동일한 주소값을 갖음

System.out.println("tv_1 = "+tv_1); // 직접 찍어보면 아래와 같이 출력됨
System.out.println("tv_2 = "+tv_2);

// 출력
tv_1 = day21.Tv@282ba1e
tv_2 = day21.Tv@282ba1e

 

3. 클래스 & 객체 활용해서 게임 만들기

  • 이전에 조건문과 반복문 공부할 때 만들었던 게임을 객체 생성을 통해서 조금 더 발전시킨 형태로 만들어 보았다.
  • game 클래스의 객체 gm 을 생성하여 이름과 레벨을 정의하고, exp 가 10 이상이 되면 게임을 종료하도록 하였다.
  • 매소드는 점프, 회피 , 공격 으로 구성되며, 각각 1 2 3 을 입력받았을 때 실행되도록 하였다.
  • 여기서 조금 더 발전시키면 나의 행동이 무조건 성공해서 문장이 출력되고 경험치가 올라가는 형식이 아닌 랜덤하게(50%) 행동에 실패하여 경험치가 깎인다던지 하면 더 좋을 듯 하다.

P.S) 역시 점프하고 회피하고 무기를 휘두르는 게임은 젤다가 가장 기억에 남아서 이름은 젤다로 넣었습니다ㅋㅋ

public class Practice_22 {
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in); // scanner import
		Game gm = new Game(); // Game 객체(인스턴스) 생성
		
		gm.name = "링크"; // gm(game)에서 사용할 이름 정의
		gm.Lv = 1; // gm(game)에서 사용할 초기 LV 정의
			
		int num; // 숫자 입력받기 위한 변수 생성
		
		for(;;) { // 무한 반복, exp 가 10 이거나 10 이상이면 종료
			System.out.println("다음중 입력해주세요");
			System.out.println("1 : 점프");
			System.out.println("2 : 달리기(회피)");
			System.out.println("3 : 공격");
			num = scan.nextInt();
			
			switch(num) { // switch 문으로 각 행동 출력
			
			case 1:
				gm.jump(); // 점프!
				System.out.println();
				break;
			case 2:
				gm.run(); // 회피!
				System.out.println();
				break;
			case 3:
				gm.weapon(); // 공격!
				System.out.println();
				break;	
			}
			
			if(gm.exp==10 || gm.exp>10) { // gm.exp 가 10 이상이면 종료
				gm.exp();
				break;
			}
		}
	}
}

class Game{
	String name; // 이름 맴버 변수
	int Lv; // LV 맴버 변수
	int exp = 0; // 초기 exp 맴버 변수
	
	void jump() { // jump 매소드
		System.out.println("현재 레벨 : "+Lv+ " 현재 경험치 : "+exp);
		System.out.println(name+" 가 점프합니다");
		exp+=2;
	}
	
	void run() { // run 회피 매소드
		System.out.println("현재 레벨 : "+Lv+ " 현재 경험치 : "+exp);
		System.out.println(name+" 가 회피합니다");
		exp+=2;
	}
	
	void weapon() { // 공격 매소드
		System.out.println("현재 레벨 : "+Lv+ " 현재 경험치 : "+exp);
		System.out.println(name+" 가 무기를 휘두릅니다");
		exp+=2;
	}
	
	void exp() { // exp 가 10 이상일때 출력되는 매소드
		System.out.println("EXP : "+exp);
		System.out.println("레벨업!! 게임을 종료합니다");
	}
}

댓글