1.접근제한자


public : 클래스 안과 밖, 패키지 안과 밖 구분없이 모든 클래스들이 접근 가능


protected : 같은 패키지나 상속 관계일 경우 접근 가능


default : 같은 패키지에 속한 클래스만 접근 가능, 따로 접근제한자를 명시하지 않으면 default로 설정 됨


private : 클래스 안에서만 접근 가능 객체화.변수같이 사용할 수 없음, 캡슐 구조의 핵심





다음은 컴퓨터의 상태(실제 상태가 아니고 임의의 값을 넣음)를 출력하는 클래스 입니다.


예제를 보고 private으로 선언된 변수를 다루는것을 확인해보자.

package chap04.exam12.prv;

import java.util.Scanner;

// Private 접근제한자를 쓰는 이유
public class Computer {
	Scanner scanner = new Scanner(System.in);	
	private boolean power; // 외부에서 보기/수정 가능
	private int panSpeed;    // 외부에서 보기/수정 가능
	private int temp;           // 외부에서는 조절 불가, 보기는 가능

	
	public boolean isPower() {
		return power;
	}

	public void setPower(boolean power) {
		this.power = power;
		if(this.power) {
			this.panSpeed = 50;
			this.temp = 60;
		}else {

		}
	}

	public int getPanSpeed() {
		return panSpeed;
	}

	public void setPanSpeed(int panSpeed) {
		this.panSpeed = panSpeed;
		this.temp = 110 - this.panSpeed;
	}

	public int getTemp() {
		return temp;
	}

	public Computer() {
		System.out.println("컴퓨터 전원을 키시겠습니까? (y/n)");
		char state = scanner.nextLine().charAt(0);

		if(state == 'y') {
			System.out.println("전원이 켜졌습니다.");
			this.power = true;
			this.temp = 30;
		}else {
			System.out.println("전원이 꺼집니다.");
			this.power = false;
		}
		
	}
	
	boolean powerState() {
		return power;
	}
	
	void powerstate() {
		if(power) {
			System.out.println("전원이 켜져있습니다.");
		}else {
			System.out.println("전원이 꺼져있습니다.");
		}
	}
	
	int panSpeedState() {
		return panSpeed;
	}
	
	void changePanSpeed(int speed) {
		this.panSpeed = speed;
		System.out.println("팬 속도가 " + panSpeed + "로 바뀌었습니다.");
		
		if(panSpeed >= 10) {
			this.temp = 20;
		}else {
			this.temp = 30;
		}
	}
	
	int tempState() {
		return temp;
	}
	
	void powerOff() {
		this.power = false;
		System.out.println("컴퓨터가 종료됩니다.");
	}
}


다음은 Main 이 computer 클래스를 불러와 각종 private 정보에 접근하는 프로그램입니다.

package chap04.exam12.prv;

import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		// 전원 켜기
		// 전원 상태 보기
		// 팬 속도 보기
		// 팬 속도 조절
		// 온도 확인
		Scanner scan = new Scanner(System.in);
		int a = 0;
		int result = 0;
		
		Computer com = new Computer();
		
		if (com.powerState()) {
			while(true) {
				System.out.println("\n어떤 처리를 하시겠습니까? (1~5 사이의 숫자 입력)");
				System.out.println("\n1. 전원 상태보기");
				System.out.println("2. 팬 속도 보기");
				System.out.println("3. 팬 속도 조절");
				System.out.println("4. 온도 확인");
				System.out.println("5. 컴퓨터 종료");
				result = scan.nextInt();
				
				switch (result) {
					case 1:
						com.powerstate();
						break;
						
					case 2:
						System.out.println("팬의 속도는 " + com.panSpeedState() + "입니다.");
						break;
						
					case 3:
						System.out.println("원하시는 속도를 입력해주세요.");
						a = scan.nextInt();
						com.changePanSpeed(a);
						break;
						
					case 4:
						System.out.println("현재 컴퓨터의 온도는 " + com.tempState() + "도 입니다.");
						break;
				}
				if(result == 5) {
					com.powerOff();
					break;
				}
			}
		}
		scan.close();
	}

}


2.Final 상수


final 키워드는 더 이상 변경이 불가능하게 설정하는 키워드이다.


즉, 변수의 값을 변경할 수 없으므로 상수라고 부른다.


그러므로 상수는 생성과 함께 초기화도 해주어야 한다.


메소드에 Final을 붙일 경우에는 상속시에도 오버라이딩이 불가능한데 이 경우는 상속에서 다시 설명한다.


다음 예제를 보고 확인해보자.



package chap04.exam09.readOnly;

public class Person {
	final String nation;
	final static String ssn; // 변경이 불가능하므로 상수(CONSTANT)
	final String name;
	
	public Person(String nation, String name) {
		this.nation = nation;
		this.name = name;
	}
	
	static { // 사실상 초기화가 불가능
		System.out.println("호오추울");
		ssn = "205938-984327";
	}
	
}


package chap04.exam09.readOnly;

public class Main {

	public static void main(String[] args) {
		Person pp = new Person("한국",  "이름");
		/* final이 붙어 있어 오류발생, 주석처리
		pp.name = "홍길동";
		*/
		System.out.println(pp.name);
		System.out.println(pp.nation);
		System.out.println(Person.ssn);
	}

}


1.Static


처음에 클래스를 설명할 때 너무 틀이라는 비유에 얽매이면 안된다고 했던게 Static 때문이다.


static은 변수와 메소드에 사용 할 수 있는데 


변수의 경우에는 같은 클래스를 이용하여 객체화 한 여러 객체들이 이 static 변수를 공유해서 사용이 가능하다.


이 static 변수는 heap 영역이 아닌 class 영역에 별도로 저장되어 공유하며 사용된다.


static은 따로 객체화하지 않고 클래스명.메서드명();와 같이 객체화없이 사용이 가능하다.


static 메소드 역시 클래스 영역에 저장된다.


사실 객체화하고 객체를 통해서 static 메소드를 호출하는것은 옳지 않다. 많이 하는 실수로 eclipse에서 자체적으로 허용해준다.


초기화는 값을 지정해줘도 되고 따로 static { } 블록을 생성해서 초기화 하여도 된다.




아래의 예제를 통해 이해해보자.



static 메소드

package chap04.exam07.sMember;

public class Sub {
	
	static int sField = 134;
	
	static int plus(int a, int b) {
		return a + b;
	}
	
	static int minus(int a, int b) {
		return a - b;
	}
	
	int multi(int a, int b) {
		return a * b;
	}
}


package chap04.exam07.sMember;

public class Main {

	public static void main(String[] args) {
		Sub cal = new Sub();
		
		System.out.println(cal.multi(3, 4) + " : 일반적인 객체화와 메서드 호출 방법을 이용");
		System.out.println(Sub.plus(3, 4) + " : Static의 특징인 생성 없이 메서드 사용.");
		// cal.plus(3, 4); 와 같이 static 메서드를 객체로 생성해서 호출하는건 옳지 않음
		// 저장되는 영역이 다르기 때문, static 영역은 클래스가 있는 영역이다.
		// 객체에서는 이 영역에 접근할 수 없으므로 클래스에서 접근하는 것이 옳다.
		// 이는 원본에 따로 표시한 내용을 복사본에서 볼 수 없는 것과 같다...
		
		System.out.println("객체 생성 후 접근 : " + cal.sField + ", " + "클래스 접근 : " + Sub.sField);
		// 일반적으로 프로그래머들이 많이 하는 실수이기 때문에 틀리더라도
		// eclipse 자체에서 객체 생성 후 접근이 가능하게 지원을 해 주지만 밑줄을 그음.
	}

}






static 변수

package chap04.exam08.sBlock;

public class Monitor {
	static String company = "LG";
	static String model = "Wide Curved Monitor";
	static int price;
	// static은 객체화가 불가능 하므로 잘 사용은 안하지만
	// static block으로 초기해도 되고 값을 바로 지정해도 된다.
	
	static {
		System.out.println(price);
		System.out.println("price 초기화");
		price = 154000;
	}
}


package chap04.exam08.sBlock;

public class Main {

	public static void main(String[] args) {
		
		
		
		
		System.out.println("Monitor 속성 호출");
		System.out.println("제조사 : " + Monitor.company);
		System.out.println("모델 : " + Monitor.model);
		System.out.println("가격 : " + Monitor.price);
	}

}


1.생성자


생성자는 객체가 생성될 때 읽을 메소드를 말한다.


메서드의 이름은 클래스와 이름을 똑같이 쓰며 매개변수를 설정하여 구현할 수 있다.


일반적으로 객체 생성시에 변수, 필드값들을 초기화 할 때에 많이 사용된다.




2.오버로드


메소드를 선언 할 때에는 매개변수를 설정하는데 종종 입력받은 매개변수가 유동적으로 바꿔야 할 필요가 있다.


물론 이름을 다르게 쓰면 문제가 없지만 사용자가 불편해지고, 또 메소드가 너무 많아지게 된다.


그러한 불편한 점을 해결하기 위한 기능이 오버로드다.


메소드의 이름은 똑같게 설정하고 매개변수는 다르게 설정한다던가 반환타입을 다르게 한다던가


예를들어 plus라는 덧셈 메소드를 만든다고 할 때에 인자를 2개 받는다고 치자.


public int Plus(int a, int b){

return a+b;

}


위와같이 쓰는데 더하기를 할 때에 소수도 들어가고 Int의 최대값인 2147483647 보다 더 큰 수가 들어갈 수도 있다.


그래서 오버로드를 사용하면


public double Plus(double a, double b){

return a+b;

}


위와같이 하면 double 타입도 무사히 덧셈을 할 수 있다.


경우에 따라서 오버로드를 잘 써주면 사용자가 매우 편리해진다.


생성자도 몰론 메소드 개념이므로 활용이 가능하다.


아래의 예제를 보고 이해해보자.



package chap04.exam03.constr;

public class Robot {
	public static int num = 1;
	public String name;
	public String goal;
	public String number;
	
	public Robot(String name, String goal) { // 객체화하면 생성자가 가장 먼저 실행 됨
		
		System.out.println("로봇 생성");
		// 초기화, 원래는 this를 사용해야 함
		name = name;
		goal = goal;
		
		number = "로봇 " + num + "호";
		System.out.println(number);
		num = num + 1;
		
	}
	// 생성자 오버로드 : 다양한 방법으로 객체 생성 가능
	// 오버로딩은 철저히 사용자의 편의를 위해 만들어짐
	// 인자값의 수나 타입이 달라야 함
	public Robot(String name) {
		System.out.println("로봇 생성");
		name = name;
		
		number = "로봇 " + num + "호";
		System.out.println(number);
		num = num + 1;
	}
	public Robot() {
		System.out.println("로봇 생성");
		name = name;
		
		number = "로봇 " + num + "호";
		System.out.println(number);
		num = num + 1;
	}

}


package chap04.exam03.constr;

public class Main {

	public static void main(String[] args) {
		Robot robot = new Robot("로오봇", "계산기");
		Robot robot2 = new Robot("건설로봇", "자동차 제작");
		Robot robot3 = new Robot();
		Robot robot4 = new Robot("건설로봇 2");
	}

}


1.클래스, 객체 지향 프로그래밍, 접근 제한자


클래스는 자바의 핵심 개념이다. 모든 java파일이 클래스 개념으로 돌아간다고 생각한다.


먼저 객체 지향 프로그래밍을 이해해야 하는데 객체지향 프로그래밍이란 객체, Object를 이용한 프로그래밍이고


객체란 현실상의 대상을 추상화하여 프로그램 상에서 구현한 결과물이다.


대상의 각각의 요소들을 합쳐 완전한 대상을 구현하는 것을 객체 지향 프로그래밍이라고 할 수 있다.




객체 지향 프로그래밍의 특징으로는 추상화(Abstraction), 캡슐화(EnCapsulation), 상속(Inheritance), 다형성(Polymorphism)이 있고


각각의 특징은 뒤에 다시 자세하게 설명하겠다.




클래스는 객체를 만들기 위한 설계도이다. 흔히 붕어빵 틀과 같은 것으로 비유를 한다. 처음 이해할 때에는 좋은 비유이다.


클래스가 다양한 변수, 메소드 등의 정보를 담고있고 그 정보를 통해 제작한 것이 객체이다.


객체를 만드는 것을 객체화, 인스턴스화라고 하며 메모리의 Heap 영역에 할당이 된다.


뒤에 나오는 Static을 배우면 붕어빵 틀과 같은 개념이 전부 무너지기 때문에 틀이라는 것에 너무 얽매이면 안된다.




여지껏 Main 클래스를 만들 때의 Main도 클래스의 하나이고 public static void main(){}도 Main의 메소드 중 하나이다.


package chap04.exam01.classDefine;

public class Main { // Main클래스는 하나의 분류가 된다.
	// Main 클래스에 속해 있는 메서드
	public static void main(String[] args) {
		

	}

}
package chap04.exam01.classDefine;

public class Sub {
	// 첫 문자가 대문자 인가?
	// 특수문자를 사용 했나? ($, _제외)
	// 파일명과 클래스 명이 일치 하는가?
	// 안의 메서드와 필드들이 대표하는 이름인가?
}



클래스 선언과 객체화는 아래와 같다.


package chap04.exam02.classIns;

public class Main {

	public static void main(String[] args) {
		// Student 를 새롭게(new) 복사하여 담는다.
		// 변수의 형태는 담을 객체의 형태여야 한다.
		
		Student std = new Student();
		System.out.println(std);
	}

}


package chap04.exam02.classIns;

public class Student {
	// 이름으로 봤을 때 학생에 관련된 내용이 있을것으로 예상할 수 있게 작명
	
	
}


객체화시에는 이름을 다르게 해서 여러개의 복사본을 만들 수 있는데 원본은 Student로 같지만 이름은 전부 다르고 각각의 객체들도 다르게 취급된다.


현실에서도 고등학생이라고 전부 똑같은 사람이 아니라 개성이 있고 이름도 다르다.


그리고 Student 클래스를 선언하고, 선언 할 때에는 누구든지 이게 어떤 내용일지 대강 알아야 한다.


왜냐하면 자바는 특성상 여러사람이 공유하여 사용 할 수 있는 확장성이 있고 실제로도 프로그래밍은 절대 혼자하는게 아니기 때문이다.


어쨋든 메인에서


Student std 로 클래스를 선언하고


= new Student(); 와 같이 객체화 한다.


필자가 받은 느낌으로는 그냥 특별한 변수를 만들어서 선언하고 초기화 하는것과 매우 유사해서 이해하기 쉬웠다.



2.접근 제한자


접근 제한자란 클래스를 통해 객체화 되어 변수나 메소드를 사용할 권한을 지정하는 것이다.


접근 제한자는 객체 지향 언어에서 캡슐화와 관련이 있고 public부터 시작해서 겉껍질, 제일 안쪽에 private으로 캡슐 구조라고 말한다.


클래스 선언 시 변수와 메서드 맨 앞에 명명하며 다음과 같이 사용한다.


[접근 제한자] [static] [변수 명];


[접근 제한자] [static] [반환 타입] [메소드 명]([매개변수]){ [내용] };


종류로는 아래와 같이 있다.


+ : public으로 선언

- : private으로 선언

# : protected로 선언

~ : default, package를 의미




3.클래스 다이어그램



먼저 클래스 다이어그램을 그릴 수 있는 사이트를 소개한다. 


https://www.draw.io


클래스 다이어그램 뿐만 아니라 플로우 차트, 표, 차트 등 다양한 그리기 도구를 지원한다.


사이트에 접속하면 처음에 어디에 저장 할 것인지 물어보는데 원하는 위치에다 설정하고


Create new diagram - Software - 첫번째를 선택하면 클래스 다이어그램을 간편하게 그릴 수 있다





클래스 다이어그램이란 프로젝트 안에 있는 클래스들의 관계를 그림으로 표현 한 것 이다.


눈에 익기만 한다면 프로그램이 어떻게 돌아가는지 쉽게 파악 할 수 있게 되고 실무에서도 문서를 읽거나 작성할 때 좀 더 편할 것이다.


아래 그림을 보고 이해해 보자



 클래스 다이어그램 예제와 기호 설명

 

 첫번째 블록 : 클래스 명

두번째 블록 : 멤버 변수

세번째 블록 : 매개 변수


두번째 블록

[접근제한자] [변수 명] : [타입]

*밑줄은 static으로 선언되었음을 표현


세번째 블록

 [접근제한자] [매개 변수 명][(인자종류)] : [타입]




예제 해석


Article 클래스


private로 선언된 String 타입 name 변수

private로 선언된 String 타입 contents 변수

public static으로 선언된 String 타입

PAGENAME_SUFFIX 변수


public으로 선언된 getName 매개변수, 반환값은 String

public으로 선언된 setName 매개변수, 인자는 String 타입 newName, 반환값은 없음

public으로 선언된 getContents 매개변수, 반환값은 String

public으로 선언된 setContents 매개변수, 인자는 String 타입 newContents, 반환값은 없음

 

Association : 대상 클래스를 변수로 사용하는 관계

Inheritance : 상속 관계를 의미함

Implementation : 인터페이스를 불러옴

Dependency : 상속하여 대상 클래스의 변수 메서드                    등을 사용

Aggregation : 추후 추가

Composition : 추후 추가

 

 접근 제한자 표기


+ : public으로 선언

- : private으로 선언

# : protected로 선언

~ : default, package를 의미

Derived, Random은 생략



클래스 다이어그램 예제 출처 : https://zetawiki.com/wiki/클래스_다이어그램

화살표 및 기호 출처 : https://en.wikipedia.org/wiki/Class_diagram

'개념 및 코딩 > 04.클래스' 카테고리의 다른 글

[JAVA]04-04.접근제한자 private, Final 상수  (0) 2018.08.24
[JAVA]04-03.Static  (0) 2018.08.24
[JAVA]04-02.생성자, 오버로드  (0) 2018.08.24

+ Recent posts