0326 Class의 접근제한자, 캡슐화

Fifty·2025년 3월 26일

2. JAVA

목록 보기
13/33

접근제한자

  • private: 멤버변수를 비밀처리, 접근제한
    → private멤버변수를 사용하기 위한 멤버함수를 생성하면 접근 가능하다.
    [예시]
    A.java
package ex0326;

public class A {
	
	private int n;
	
	// private로 선언된 n의 값을 설정해주는 setter
	public void setN(int n) {
		this.n=n;
	}
	// private로 선언된 n의 값을 외부로 반환해주는 getter
	public int getN() {
		return n;
	}
}

ATest.java

package ex0326;

public class ATest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		A a = new A();
		System.out.println(a.getN());
		a.setN(10);
		System.out.println(a.getN());
	
	}
}
  • public: 멤버변수를 공개화, 접근가능

vo: value object - 값을 저장하는 용도의 클래스 이름 뒤에 붙기도 함.
dto: data transotation object - 데이터를 전송할 때 이름 뒤에 붙이기도 함.

캡슐화

  • 정보은닉(information hiding): private
    은닉된 정보에 접근할 수 있는 public이 있어야한다. ex: getter, setter

toString()

인스턴스의 멤버변수의 값을 제공하는 기능을 하는 것으로 약속되어 있다.
toString()가 없이 참조변수를 출력하면 주소가 나오지만
toString()이 있다면 참조변수 출력시 정보가 출력된다.

toString() 없을 때,

toString() 없이 toString()을 출력하면 주소값이 출력된다.

toString() 있을 때,

@Override

컴파일러에게 메서드를 오버라이딩하는 것이라고 알림.
어노테이션(Annotation): 다른 프로그램에게 유용한 정보를 제공하기 위해 사용되는 것으로 주석과 같은 의미

이미 정의되어있는(만들어져있는) 메소드의 이름을 변경하고 toString() → toStrings()
@Override라고 어노테이션을 작성해주면 오류가 난다.

오버라이딩: 함수의 시그니처는 같아야하지만, 기능이 다르다.
오버로딩: 함수의 시그니처가 다르다. 이름은 같다.


[예제]

사람(Human) 클래스를 만드시오.

사람은 아무정보도 없는 상태로 태어날 수 있습니다.
생성된 후 사람은 이름과 나이를 부여받습니다.

이 때 나이는 1살부터 200살 사이의 값이어야 합니다.
만일 나이가 범위 밖의 값으로 부여된다면 '값의 허용범위를 벗어났어요.'라는 메시지를 콘솔에 출력합니다.
그리고 나이는 자동으로 0살로 셋팅합니다.

사람 객체(인스턴스)의 정보(이름, 나이)를 하나의 문자열로 구성할 때 나이가 0살이면 나이값은 '미정'이라고 해주십시오.

추가!
사람은 이름과 나이를 부여받아 생성될 수도 있어야합니다.

Human.java

package vo;

import java.util.Scanner;

public class Human {
	private int age;
	private String name;
	
	public Human(){
		// 아무 정보도 없는 상태로 태어날 수 있음
		// 생성된 후 이름과 나이를 부여받는다.
		Scanner sc = new Scanner(System.in);
		System.out.println("나이를 입력하세요 > ");
		setAge(sc.nextInt());
		System.out.println("이름을 입력하세요 > ");
		setName(sc.next());
	}
	
	public void setAge(int age) {
		this.age=age;
	}
	
	public void setName(String name) {
		this.name=name;
	}

	public int getAge() {
		return age;
	}
	public String getName() {
		return name;
	}
	
	
	public Human(int age, String name){
		// 나이가 1~200살의 범위를 벗어나면 메시지 출력 및 0으로 셋팅
		if(age<1 || age>200){
			System.out.println("값의 허용범위를 벗어났어요.");
			this.age = 0;
		}else
			this.age = age;
		this.name = name;
	}

	@Override
	public String toString() {
		// 나이가 0살이면 나이값은 '미정'이라고 출력
		if(age==0)
			return "Human [age=미정, name=" + name + "]";
		else
			return "Human [age=" + age + ", name=" + name + "]";
	}
}

HumanTest.java

package ex0326;

import vo.Human;

public class HumanTest {

	public static void main(String[] args) {
		
		
		Human h = new Human(210, "Hong");
		System.out.println(h.toString());
		
		Human h2 = new Human();
		System.out.println(h2.toString());
		
		Human h3 = new Human(3, "Kim");
		System.out.println(h3.toString());
	}
}

결과


[추가]
나이를 검증하는 기능을 별도의 함수로 만드시오.
단, 그 함수는 해당 클래스의 멤버만 사용할 수 있습니다.

→ 나이를 검증해서 범위 안에 있다면 true, 벗어났다면 false를 출력해주는 checkAge함수를 private로 해주자.
→ setAge에서 나이검증함수를 호출해주자.

setAge함수를 수정하고 나이검증함수를 추가해주었다.

	public void setAge(int age) {
		if(checkAge(age)) this.age=age;
		else{
			System.out.println("값의 허용범위를 벗어났어요.");
			this.age=0;
		}
	}	
    
    // 나이를 검증하는 함수
	private boolean checkAge(int age) {
		if(age<1 || age>200) return false;	// 범위 벗어나면 f
		else return true;	// 범위 안에 있다면 t
	}

[예제]
날짜정보를 저장하는 vo class
1. class 이름: MyDate
2. 멤버변수(int): 연도, 월, 일

  • 연도는 정수면 됨
  • 월(1~12), 일(1~28,29,30,31)은 달력에 나온 수를 활용

MyDate.java

package vo;

import java.util.Scanner;

public class MyDate {
	private int year;
	private int month;
	private int day;
	
	public MyDate(int year, int month, int day){
		setYear(year);
		setMonth(month);
		setDay(day);
	}
	
	public int getYear() {
		return year;
	}
	public void setYear(int year) {
		this.year = year;
	}
	public int getMonth() {
		return month;
	}
	public void setMonth(int month) {
		if(checkMonth(month))
			this.month = month;
		else{
			System.out.println("월을 다시 입력하세요");
			Scanner sc = new Scanner(System.in);
			this.month = sc.nextInt();
		}
	}
	public int getDay() {
		return day;
	}
	public void setDay(int day) {
		if(day>=1 && day<=checkDay(year, month, day))
			this.day = day;
		else{
			System.out.println("일을 다시 입력하세요");
			Scanner sc = new Scanner(System.in);
			this.day = sc.nextInt();
		}		
	}
	
	@Override
	public String toString() {
		return "MyDate [year=" + year + ", month=" + month + ", day=" + day + "]";
	}
	
	private boolean checkMonth(int month) {
		if(month>=1 && month<=12) return true;
		else return false;
	}
	
	private int checkDay(int year, int month, int day) {
		switch(month) {
			// 2월은 윤년확인해서 28일 혹은 29일
			case 2:
				if(year%4==0)
					if(year%100==0)
						if(year%400==0)
							return 29;
						else return 28;
					
					else return 29;
				else return 28;
			case 4: return 30;
			case 6: return 30;
			case 9: return 30;
			case 11: return 30;
			default: return 31;  // 1, 3, 5, 7, 8, 10, 12월
		}
	}
	
}

DateTest.java

package ex0326;

import vo.MyDate;

public class DateTest {

	public static void main(String[] args) {

		MyDate md = new MyDate(1996, 2, 29);
		System.out.println(md.toString());
		
	}

}

결과1

결과2: 윤년(1996년)이 아닌데 2월 29일을 입력

0개의 댓글