객체지향 - 인스턴스, 정보은닉

 

Main Class

import java.util.Scanner;

public class Exam_04 {
	public static void main(String[] args) {
		Monitor mon=new Monitor();
		//첫글자가 대문자이니까 클래스구나, 참조자료형이구나, mon이라는 변수이구나
		//Monitor라는 참조자료형은 java 자체에는 없지만 내가 Monitor라고 Class(Class파일)을 만든 것이 참조자료형이 된 것
		//mon이라는 변수를 만들었다고 해서 class안에 있는 price,color,poweron,poweroff가 생기지 않음 (프로그램이 public class Monitor 밑으로 내려가지 않았음!!?!?)
		//mon은 참조자료형변수이니까 stack에 mon이라는 참조형변수가 만들어지고 mon의 안에는 heap으로 찾아갈 주소값이 들어갈 것이다.
		//Monitor라는 Class는 설계도가 길어질 수도 있고 짧아질 수도 있는 가변적이다.
		//가변적인건 Heap에 저장된다!
		
		//Heap에 만들겠다는 의미로 new를 쓴다
		//램 안의 Heap메모리 안에 모니터 설계도(Monior Class)를 바탕으로 모니터가 만들겠다는 의미
		//new Monitor  ===> Heap영역에 만들어진 모니터의 주소값(ex.1000번지)
		//그 주소값을 어디엔가 사용하기 위해서 sc.nextline()처럼...
		//mon 변수 안에  모니터의 설계도를 바탕으로 만든 모니터(인스턴스)의 주소값을 저장 
	
		//인스턴스(instance)=객체 
		//new 연산자를 통해 메모리(Heap)에 실체화된 데이터
		//new 연산자를 통해 인스턴스를 생성해야만!!!!! 실제로 만들어지는 것이다
		
		//RAM(Heap)안에 실존하는 모니터 인스턴스가 기능을 하게 하려면 내가 말을 걸어야함
		
		mon.powerOn();
		//mon.(인스턴스접근연산자)
		//인스턴스접근연산자를 사용하는 것 -> mon이라는 참조형 변수가 가진 주소로 찾아가라는 의미인거임
		//new를 하지 않았다면 인스턴스(객체)가 만들어지지 않았기 때문에,실존하지 않기 때문에 주소값이 없어서 .이후에 monitor 안에가 나올 수가 없음!!!!
		
		//필드=변수
		
		Scanner sc = new Scanner(System.in);
	//	sc.nextLine();
		//Scanner라는 설계도를 바탕으로 만든 스캐너를 
		//new연산자를 통해 메모리(Heap)에 실체화한 데이터의 주소값을 저장한 변수 sc!!!
		//자바를 설치했을 때 자동으로 설치되는 것 --> jre system library
		//jre system library 에 있는 Scanner 라는 클래스(설계도)를 이용하여 
		//new Scanner -> Heap에 인스턴스(객체)를 만든 것임!!!
		//그걸 참조형변수 sc에 넣은거임
		
		//기억해야할 것 -> 매개변수,지역변수는 무조건 스택 영역에 있음!!!
	
		
		//mon.price=1000;
		//클래스 내부에 있는 걸 알고 강제로 사용하려고 해도, 사용할 수가 없다.
		//직접 넣을 순 없지만~ Monitor클래스에서 만든 public한 setPrice Method를 이용하면 넣을 수 있다. 제한된 접근~?
		mon.setPrice(1000);
		//System.out.println(mon.price);
		//클래스 내부에 있는 걸 알고 있지만 Private로 선언되어있기 때문에 가져올 수가 없다.
		System.out.println(mon.getPrice());
		System.out.print("새로운 가격을 입력하세요 >");
		mon.setPrice(Integer.parseInt(sc.nextLine()));
		System.out.println("새로운 가격은? ");
		System.out.println(mon.getPrice());
		
		mon.setColor("black");
		System.out.println(mon.getColor());
		System.out.println("새로운 색상을 입력하세요.");
		mon.setColor(sc.nextLine());
		
		mon.getThis();
		//getThis -> mon 자기자신의 주소를 다시 불러오는것(1000번지)
		mon.getThis().getThis();
		// 무한 창조가 가능하다?
		//메써드를 만들고 메써드를 만들고
		//설정을 한번에 하는게 아니라, 연속적으로 콜하면서 주는 것 (체이닝chaining기법)
		System.out.println(mon.getThis());     
		System.out.println(mon.getThis().getThis());
		//mon.getThis();
		//mon.getThis().getThis(); 
		//둘다 같은 주소를 가리키고 있다.
	
		
		Tv tv = new Tv();
		//tv.channel=-10;
		//클래스 내부에 있는 걸 알고 강제로 사용하려고 해도, 사용할 수가 없다.
		
	}
}

 

Monitor Class

public class Monitor {
	//정보은닉 -> """접근제한자"""와 관련
	//접근제한자
	//public > protected > package > private
	//퍼블릭		프로텍티드		패키지	프라이빗
	//public, private가 중요!! 자주쓰임
	//protected, package는 그리 많이 안쓰임


	private int price;
	private String color;
	//this : 자기참조변수     자기(self)
	//main에서 생성한 모니터 인스턴스 mon은 자아가 있음. 밖에서 부를때 그 인스턴스를 부를때 mon이라고 부름
	//클래스 내부에서는 자기자신을 부를 수 없음. 자기자신, 내 필드, 내 기능을 못봄 -> 나를 뭐라고 불러야할지 모름.
	//클래스가 클래스 자신을 볼 수 있는, 클래스가 클래스 안에서 (.)찍어서 필드와 기능을 볼 수 있도록 해줌 
	//this도 필드이다(멤버필드~~~~~)
	//Monitor형(참조형)변수 mon
	//자바의 문법 안에는 작성하지 않으면 있는 걸로 치는 자기 자신에 대해서 암묵적으로 한 것들이 존재함
	//예 : import java.lang.*;
	//private final Monitor this; 라는게 눈에 보이지 않지만 존재함.... 글구 직접 쓰면 안댐!!! -> 자기참조변수 
	
	//setThis는 없음
	
	public Monitor getThis() {
		return this;
		//자기자신의 주소를 내보내는 것
		//참조형은 왜 Monitor? Monitor형을 만든거니까
	} 
	
	//public  공적인 (다른 클래스에서 볼 수 있고, 사용할 수 있음)
	//private 사적인 (다른 클래스에서 볼 수 없고, 사용할 수 없음)
	//~~~~~정보은닉을 이용하는 첫번째 이유~~~
	//정보은닉을 이용하여 
	//채널이나 볼륨 같은 것들을
	//개발자의 의도대로 사용자가 오류나지 않는 상황에서 사용할 수 있도록 유도하게 할 때 유용
	//~~~~~정보은닉의 권고사항~~~~(오라클의 권고사항)
	//멤버필드가 만들어졌다하면 일단 private를 쳐라~!
	//외부에서 사용할 수 있도록 method를 public으로 제공해 줘서  사용자를 통제하도록~~~
	//제작자의 안정성을 위해서 하는 통제

	//바깥 사용자들이 클래스를 이용 인스턴스를 만든 것에.(인스턴스접근연산자) 이후 보이는 것들은 모두 public임
	//정보은닉을 이용하는 두번째 이유
	//외부에 공개할 필요가 없는 or 공개해서는 안되는 내용을 숨기기 위함
	//안그래도 복잡한데 사용자가 자기가 써도 되는, 써야하는 것 외에 보이는게 너무 많으면 혼란스러우니까
	//사용자에게 공개할 수 있는(보여줄 수 있는) 부분만 보여주면 사용자가 편리해짐
	//사용자의 편의성을 위해서 하는 통제	

	//getter와 setter의 매개변수명은 멤버변수명과 동일하게 작성한다
	//private field 하나당 2개의 method를 만들어주게 되는데--> 해당 필드에 값을 집어넣을때, 해당 필드에 값을 꺼내올때	
	//private 멤버변수 price에 값을 집어넣고 싶을때
	//private로 선언된 멤버필드에 외부에서 들어온 값을 집어 넣는 컨벤션 : set+필드명
	//외부에서 가져온 값을 집어넣는 메쏘드 Setter/Setters라고 한다
	public void setPrice(int price) { //매개변수 price:바깥에서 가져온 가격 
		//매개변수는 class의 소유가 아님
		//매개변수는 method의 소유임(잠시 만들었다 사라지는 것)


		//price = price;//매개변수에 매개변수를 넣게 되버림 -> 이름이 겹쳤을때 보편적으로 가까운 걸 사용하게 됨(stack에서 가까운 곳 stack은 아래에서 위로 쌓이니까?)
		//그것을 해결하는 방법은
		//this라고 하는 키워드가 앞에 붙는 것은 멤버를 뜻한다. 나 자신의 멤버!
		this.price=price;//this가 앞에 붙은 것은 멤버니까 멤버변수 price에 매개변수 price를 넣으라는 뜻이됨.

		//외부에서 들어오는 값을 넣어주는 목적이니까 return값이 없다 = 리턴값이 void이다.
		//this.price=price; 없이 그냥 불러오기만 하면? 
		//매개변수가 method가 끝나 사라지기 전에 price에 매개변수에 들어있는 값을 넣어줘야 비로소 외부에서 들어오는 값을 넣어주는 역할을 한다.
	}

	//private로 선언된 멤버필드의 값을 외부서 가져가는 컨벤션 : get+필드명
	//인자값이 필요없다 ->바깥에서 먼가 가져오는게 아니라 외부의 값을 꺼내가는 것이라서
	//return값이 있다 ->멤버필드의 값을 외부로 보내야하기 때문에
	//Private선언된 멤버필드의 값을 외부로 return해주는 Method를 Getter/Getters라고 한다
	//return 자료형에 따라 메쏘드 앞에 자료형을 붙여준다.
	public int getPrice() {
		return price;
		//private로 선언된 price가 갖고 있는 값을 return 해준다.
	}

	
	public void setColor(String color) {
		this.color=color;
	}
	public String getColor() {
		return color;
	}
	//Getters와 Setters는 클래스에 필수적으로 존재하게 됨

	//main method를 포함한 class에서 Monitor 설계도로 모니터가 new로 인스턴스가 만들어지면 
	//그 아래의  멤버변수 price,color가 만들어짐
	//price,color 같은 멤버변수들은 인스턴스가 탄생했을때 스택에 만들어졌다가 인스턴스 사라질때 없어진다
	//지역변수는 해당 Method가 생성되었을때 만들어졌다가 Method가 끝날때 사라짐
	//멤버변수는 Method의 생존여부와 상관없이 인스턴스의 생존여부를 따라간다
	//Method가 끝났어도 인스턴스가 살아있다면 멤버변수는 살아있다

	//인스턴스가 사라지는 타이밍은(상황에 따라 다르지만)
	//레퍼런스(참조)가 모두 끊겼을 때가 사라진다


	void powerOn() {
		int a; //Local variable 로컬 버라이어블(지역변수)

	}
	void powerOff() {}


	//클래스 내부를 구성하는 것 
	//1. Field 필드=변수  그냥 지역변수나 그런게 아니고~----> 멤버필드=멤버변수
	//2. Member Method멤버메써드
	//3. Constructor : 컨스트럭터(생성자)
	//4. Nested Class : 중첩클래스(클래스 안에서 클래스를 만드는 것)

}

 

 

Tv Class

public class Tv {
	//int channel;

	//TV의 채널을 바꾸려면 제조사에서 제공한 리모콘이나 버튼을 사용하여야함.
	//리모콘이나 버튼이 없으면 채널을 바꿀 수 없음 =통제 받고 있다? =public하지 않다.

	//channel은 private하게 막아놓고, channel을 선택할 수 있는 수단(리모콘,버튼)을 준것
	//channel의 1번에서 리모콘로 채널 down을 눌렀을때 0이나 -1이 아닌 999번이 나오는것 =통제를 받고 있다

	//매번 예외상황에 대한 코드를 쓰는건 너무 많은 일이다~
	//개발자는 사용자가 클래스를 이용할때 내 의도대로만 사용할 수 있게끔 통제
	//채널을 입력할때 아예 음수를 받지 못하도록 통제하는 것

	private int channel;
	//채널은 사적으로 프라이빗하게 막혀있음/사용자는 채널이 안보임

	public void channelDown() {
		//	channel--;
		//public으로 공개된 channelDown이라는 Method가
		//channel은 볼 수 없지만, 공개된 Method를 통해서~ channel의 값을 -1 시킬 수 있게 됨.
		//그냥 단순히 channel--;로만 하면 음수도 입력 받게 됨 
		
		
		if (channel>0) { 
			//사용자가 channel을 볼 수는 없지만,
			//public으로 공개된 Channel down Method를 통해~ 
			//if조건문으로 channel이 0보다 클때만
			channel--; // 채널을 -1 감소시킬 수 있도록~!
			//사용자가 channel에 직접접근은 할 수 없지만, 메쏘드를 통해서 통제할 수 있게 함
		}
	}
	
	//~~~~~정보은닉을 이용하는 첫번째 이유~~~
	//정보은닉을 이용하여 
	//채널이나 볼륨 같은 것들을
	//개발자의 의도대로 사용자가 오류나지 않는 상황에서 사용할 수 있도록 유도하게 할 때 유용
	//~~~~~정보은닉의 권고사항~~~~(오라클의 권고사항)
	//멤버필드가 만들어졌다하면 일단 private를 쳐라~!
	//외부에서 사용할 수 있도록 method를 public으로 제공해 줘서  사용자를 통제하도록~~~
	//private field 하나당 2개의 method를 만들어주게 되는데--> 해당 필드에 값을 집어넣을때, 해당 필드에 값을 꺼내올때
	//제작자의 안정성을 위해서 하는 통제
	
	//바깥 사용자들이 클래스를 이용 인스턴스를 만든 것에.(인스턴스접근연산자) 이후 보이는 것들은 모두 public임
	//정보은닉을 이용하는 두번째 이유
	//외부에 공개할 필요가 없는 or 공개해서는 안되는 내용을 숨기기 위함
	//안그래도 복잡한데 사용자가 자기가 써도 되는, 써야하는 것 외에 보이는게 너무 많으면 혼란스러우니까
	//사용자에게 공개할 수 있는(보여줄 수 있는) 부분만 보여주면 사용자가 편리해짐
	//사용자의 편의성을 위해서 하는 통제	
	

}