Wanna be Brilliant Full-Stack Developer

Java 객체지향 프로그래밍 이해 클래스의 상태와 행위 본문

Some Memos/Java

Java 객체지향 프로그래밍 이해 클래스의 상태와 행위

Flashpacker 2023. 2. 10. 16:59

 


클래스와 상태와 행위에대해 알아보자

자동차라는 클래스가 있다.

자동차라는 클래스는 상태를 먼저 보면 자동차는 현재 색상은 파란색! 

자동차의 이름은 소나타, 자동차의 브랜드는 현대, 이 자동차의 파워(엔진)은 2000cc이다.

이 자동차의 스피드는 현재 0이다. 아직 출발하지 않았기 떄문이다. 

이런 자동차의 상태가 있다. 

그런데 색상은 파란색인데 나중에 자동차를 튜닝샵에 맡겨서 변경할 수 있다.

하지만 이름과 브랜드는 변경할 수 없다. 엔진은 마음만먹으면 변경할 수 있다.

여기서 스피드는 0인데 이것이 가장 중요하다.

이 상태 값중에 스피드를 눈여겨봐야한다. 지금은 0이다 .

스피드는 언제 변할까? 속력이라는것은 자동차가 움직이기 시작하면 스피드가 변한다.  

여기서 움직인다라는 의미는 행위를 말한다!

여기서 자동차는 어떤 행위를 가질수 있는가? 움직이기 위해서 엑셀이라는 행위가 있을것이다.

왜 괄호가 있는가? 메서드기 떄문이다. 행위는 메서드이다.

상태는 필드이다!  그다음에는 브레이크가 있다. 두가지의 행위가 있다고 보자! 

 

그러면 엑셀이라는 행위가 시작되면 상태중에 무엇이 변해야하는가? 

스피드가 변해야한다! 액셀을 밟고 스피드가 막 올라갔다.

그러다가 브레이크를 밟으면 무엇이 변하는가? 스피드가 변해야한다. 

 

여기서 아주 중요한 개념이 나오는데 객체지향 프로그래밍에서 OOP라고 하는데!

오브젝트를 지향하는 프로그래밍이다! 

오브젝트가 무엇인가? 자동차 클래스가 오브젝트이다. 

이 객체지향프로그래밍에서는 원칙이 있다.

첫번째 상태는 스스로 변하는것이 아니라 행위에 인해서 변한다

다시 말하면 클래스의 필드는 메서드에 의해서 변한다.

 

이걸 기억하면서 예재를 한번해보자 

Player이라는 클래스를 만든다!

그리고 이 상태를 초기화 하기 위해서는 생성자가 필요하다!

생성자를 만들자

 

그리고 스택으로 받은 변수들의 값들을 heap에다가 넘겨주기 위해서는 this!

기본 클래스가 만들어졌고! 그다음에는 Player 객체(오브젝트)를 만들자 

new를 해서 인스턴스를 만들어보자 

오류가 나온다 왜냐하면 디폴트 생성자가 없기 떄문에!

첫번쨰로 이름은 홍길동, 목마름은 100 엄청 목마르게 태어났다

목마른걸 해결하기 위해서 .  

밑에 p1에 새로운 50을 추가 해줬다.

이게 프로그램에서 가능한것은 20 번라인에서 홍길동의 갈증 지수를 50으로 아무 원인 없이 갈증지수가 변경 = 마법 

원인 없이 상태가 변경되면 이걸 객체지향 프로그래밍이라 하지 않는다. 이건 잘못된 프로그램이다! 

 

그러면 어떻게 해야한느가? 

이번에는 Player의 상태가 두개 있는데 행위를 만들어보려고 한다. 

행위에서 무엇을 할것인가? 기존에 있는 thirty에 접근할거니까 this.

물을 한번마실때마다 갈증지수가 50이 떨어지는것이다.  행위를 만들었다. 

package ch05;

class Player {
	// 상태 = 필드 , 전역변수
	String name; //이름
	int thirty; // 목마름 (0~100)
	
	public Player(String name, int thirty) {
		this.name = name;
		this.thirty = thirty;
	}
	
	//행위 = 메서드 
	void 물마시기() {
		System.out.println("물마시기 행위");
		this.thirty = this.thirty - 50;
	}
}

public class OOPEx01 {

	public static void main(String[] args) {
		Player p1 = new Player("홍길동", 100);
		System.out.println("이름은 " + p1.name);
		System.out.println("갈등지수 : " + p1.thirty);
		
		//1. 첫번쨰 시나리오 = 마법(x) 
		// p1.thirty = 50; // 원인없이 갈증지수 변경 = 마법 
		// System.out.println("갈등지수 : " + p1.thirty);
		
		//2. 두번쨰 시나리오
		p1.물마시기();
		System.out.println("갈등지수 : " + p1.thirty);
	}

}

물마시기라는 행위를 하게 되니까 갈증지수가 50이 줄어들었는데 이것이 객체지향프로그래밍이다. 

근데 이렇게 하면 안된다!! 왜냐하면 행위를 통해서 상태를 변경하는것은 맞는데

 

내가 이렇게 코드를 짜놓은 상태에서 신입한테 물마시기라는 행위를 해줘 

너가 33번 라인만 만들어줘 물마시기해서! 라고 하면

팀장님 물마시기를 왜 하는거죠? 갈증지수를 50낮추면 되는거거든

물마시기를 하면 갈증지수가 50 낮춰지니까 물마시기를 꼭 실행해서 갈증지수를 낮춰줘!

신입이 이 상태에서 코드를 보고 목마름(thirty)있는것을 보고 100을 보고 50 정도를 낮춰주라는거구나 라고 깨닫고

p1.thirty라고 하는데 안된다.

실수할 수 있는 가능성의 코드를 만들면 안된다.

 

3번째 시나리오를 가보자 접근제어라는것을 배웠다.

접근제어자의 default를 배웠고 , public 접근제어자를 배웠다. , private 접근제어자도 배웠다!

Public이 앞에 적혀있으면 모든 다른클래스 말고도 모든 다른 패키지에서도 찾을 수 있다.

지금은 아무것도 앞에 안붙어 있으니 default접근제어자이고, 내패키지 내부, ch05어디에서도 접근이 가능하다. 

private 을 붙여 놓으면 외부 클래스에서 접근이 불가능하다.

이렇게 팀장이 만들어 놓으면 

이 코드가 오류가 난다.

왜 오류가 나는가? OOPEx01 클래스에서는 thirty라는 변수를 찾을 수 없다. 

private으로 감쳐줘 있기떄문에 볼수가없다. 

private을 붙이고 이 값을 변경할 수 있는 유일한 애는 물마시기이다. 

값을 변경할 수는 있지만 접근은 불가능하다.

 접근이 안되기 떄문에 접근이 가능한 메서드를 만들어야한다. 

void라고 하면 안되고 thirty는 int로 return this.thirty; 

thirty로 다에이렉트로 접근은 못하지만 어떤 행위를 통해서 접근이 가능하다. 

 

3번쨰 시나리오에서는 p1.thirty라고 하면 아까와 같은 The field Player.thirty is not visible이라고 오류가 나온다.

실수를 방지할 수 있다. 팀장님이 물마시기를 통해서 변경하라고 한것을 기억할 수 있다.

 

package ch05;

// 접근제어자 = 디폴트 접근제어자, public 접근제어자, private 접근제어자를 배웠다.
class Player {
	// 상태 = 필드 , 전역변수
	String name; //이름
	private int thirty; // 목마름 (0~100)
	
	public Player(String name, int thirty) {
		this.name = name;
		this.thirty = thirty;
	}
	
	//행위 = 메서드 = 값을 변경
	void 물마시기() {
		System.out.println("물마시기 행위");
		this.thirty = this.thirty - 50;
	}
	
	int 목마름상태확인() {
		return this.thirty;
	}
}

public class OOPEx01 {

	public static void main(String[] args) {
		Player p1 = new Player("홍길동", 100);
		System.out.println("이름은 " + p1.name);
		System.out.println("갈등지수 : " + p1.목마름상태확인());
		
		//1. 첫번쨰 시나리오 = 마법(x) 
		// p1.thirty = 50; // 원인없이 갈증지수 변경 = 마법 
		// System.out.println("갈등지수 : " + p1.thirty);
		
		//2. 두번쨰 시나리오 = 상태가 행위를 변경함 (X) - 실수할 수 있음(신입)
		//zp1.물마시기();
		//	p1.thirty = 50;
		//	System.out.println("갈등지수 : " + p1.thirty);
		
		//3. 세번쨰 시나리오 
		p1.물마시기();
		System.out.println("갈등지수 : " + p1.목마름상태확인());
	}

}

이것이 객체지향 프로그래밍이다!

세번쨰 시나리오대로 프로그램을 만들어야한다


객체지향 프로그래밍에서는 가장 중요한것이 상태는 행위를 통해 변경한다! 

하지만 누군가는 상태를 직접 변경할 수 있기 때문에 직접 접근하지 못하게 상태 앞에는
접근제어자 Private를 붙여야한다 그래야지 신입이 상태에 직접 접근하지 못한다.