[JAVA] 접근 제어 지시자

접근 제어 지시자 (accesss modifier)


▶ 클래스 외부에서 클래스의 멤버 변수, 메서드, 생성자를 사용할 수 있는지 여부를 지정하는 키워드


● private : 같은 클래스 내부에서만 접근 가능 ( 외부 클래스, 상속 관계의 클래스에서도 접근 불가)
● 아무것도 없음 (default) : 같은 패키지 내부에서만 접근 가능 ( 상속 관계라도 패키지가 다르면 접근 불가)
● protected : 같은 패키지나 상속관계의 클래스에서 접근 가능하고 그 외 외부에서는 접근 할 수 없음
● public : 클래스의 외부 어디서나 접근 할 수 있음

get()/ set() 메서드

● private 으로 선언된 멤버 변수 (필드)에 대해 접근, 수정할 수 있는 메서드를 public으로 제공
get() 메서드만 제공 되는 경우 read-only 필드
● 이클립스에서 자동으로 생성해주는 단축 기능이 존재한다. 

 

set 은 변수값을 할당하는 목적의 함수이기 때문에 인자를 받아야 하고
get 은 변수값을 반환하는 목적이기 때문에 return 이 필요합니다.

 

get/set 메서드를 사용하는 이유

모든 프로그램이 그렇겠지만 외부로부터 변수값에 직접적으로 접근하는 것을 막고있습니다.
직접 접근하게 되면 무결성이 깨질 수 있기 때문입니다.


자바에서는 함수를 통해 값을 전달받고, 전달하고 방식을 권장하고 있습니다.
또한 클래스 내에서 변수는 private(캡슐화, 정보은닉)로 선언하여 외부에서 바라볼 수 없도록 해야 합니다.

 

정보 은닉


● private으로 제어한 멤버 변수도 public 메서드가 제공되면 접근 가능하지만 변수가 public으로 공개되었을 때보다 private 일때 각 변수에 대한 제한을 public 메서드에서 제어 할 수 있다.
●  객체 지향 프로그램에서 정보 은닉은 필요한 외부에서 접근 가능한 최소한의 정보를 오픈함으로써 객체의 오류를 방지하 클라이언트 객체가 더 효율적으로 객체를 활용할 수 있도록 해준다.

public void setMonth(int month) {

if ( month < 1 || month > 12) {

isValid = false;

} else {

this.month = month;

}

}

캡슐화 (encapsulation)


정보 은닉을 활용한 캡슐화

● 꼭 필요한 정보와 기능만 외부에 오픈함
● 대부분의 멤버 변수와 메서드를 감추고 외부에 통합된 인터페이스만은 제공하여 일관된 기능을 구현 하게 함
● 각각의 메서드나 멤버 변수를 접근함으로써 발생하는 오류를 최소화 한다.

접근제어지시자 예제

private 사용 Bank클래스 설계

public class Bank {

// 정보 은닉

 

// 접근 제어 지시자 private - 자기 자신에서만 사용 가능

// 내부 접속 막을 때 프라이빗 사용

private String name; // 계좌 번호

private int balance; // 계좌 잔액

 

// 입금

public void deposit(int money) {

this.balance += money;

}

 

// 출금 - 도전 (잔액 0원인데 출금 요청)

public void whitdraw(int money) {

// 메서드 영역 안에 사용하는 변수는 지역 변수라고도 한다.

// int result = 0;

// this.balance -= money;

// result = money;

if (this.balance < money) {

// 잔액 금액보다 요청 금액이 크다.

System.out.println("현재 계좌 잔액이 부족합니다.");

} else {

this.balance = this.balance - money;

 

}

}

 

// 잔액 확인

public void showinfo() {

System.out.println(" == 잔액 조회 == ");

System.out.println("현재 계좌 잔액은 " + balance + "입니다.");

}

 

}

객체 사용

public class BankMainTest {

 

// 메인 함수

public static void main(String[] args) {

 

Bank bank = new Bank();

// System.out.println(bank.balance); private 사용불가

// System.out.println(bank.name); private 사용불가

// bank.showinfo();

// System.out.println(bank.showinfo); // <-- 오류 발생(showinfo 사용)

bank.showinfo();

 

bank.whitdraw(5_000);

bank.showinfo();

 

bank.deposit(20000);

 

bank.showinfo();

bank.whitdraw(5_000);

bank.showinfo();

 

// 신입이 실수를 한 코드

// bank.balance = 100_000;

// bank.showinfo();

 

} // end of main

 

} // end of class

결과

== 잔액 조회 ==

현재 계좌 잔액은 0입니다.

현재 계좌 잔액이 부족합니다.

== 잔액 조회 ==

현재 계좌 잔액은 0입니다.

== 잔액 조회 ==

현재 계좌 잔액은 20000입니다.

== 잔액 조회 ==

현재 계좌 잔액은 15000입니다.

예제2

hero클래스

public class Hero {

private String name;

private int hp;

private int power;

private int level;

private double defense;

 

// 생성자

public Hero(String name) {

this.name = name;

} // end of Hero

 

// ※ getter, get 메서드 ※

public String getName() {

return name;

} // end of getName

 

public int getHp() {

return hp;

} // end of getHp

 

public int getPower() {

return power;

} // end of getPower

 

public int getLevel() {

return level;

} // end of getLevel

 

public double getDefense() {

return defense;

} // end of getDefense

 

// ※ setter 메서드 ※

// 단, 방어적 코드도 작성해 주세요.

// ※ get, set 메서드는 무조건 설계해 주는 것이 아니라

// 필요하다면 사용하는 개념이다.

 

public void setHp(int hp) {

// 방어적 코드를 작성한다.

if (hp <= 0) {

System.out.println("잘못 입력하였습니다.");

} else {

this.hp = hp;

}

 

} // end of setHp

 

public void setPower(int power) {

// 방어적 코드를 작성한다.

if (power <= 0) {

System.out.println("잘못 입력하였습니다.");

} else {

this.power = power;

}

 

} // end of setPower

 

public void setLevel(int level) {

// 방어적 코드를 작성한다.

if (level <= 0) {

System.out.println("잘못 입력하였습니다.");

} else {

this.level = level;

}

 

} // end of setLevel

 

public void setDefense(double dfense) {

if (dfense <= 0) {

System.out.println("잘못 입력하였습니다.");

} else {

 

}

 

} // end of setDefense

 

// 기능

public void attack() {

System.out.println("공격을 합니다.");

} // end of attack

 

public void beAttaked(int demage) {

this.hp -= demage;

} // end of beAttaked

 

}

hero객체

public class HeroMainTest {

 

public static void main(String[] args) {

Hero hero1 = new Hero("홍길동");

hero1.setHp(-5);

hero1.setPower(1000);

hero1.setLevel(501);

hero1.setDefense(1030.4);

// System.out.println(hero1.setHp(0)); 안됨

 

// System.out.println(hero.power); 사용이 아닌 아래 코드로 작성

// hero1.getHp();

//System.out.println(hero1.getPower());

int returnHp = hero1.getHp();

int returnPoewr = hero1.getPower();

int returnLevel = hero1.getLevel();

double retuDefense = hero1.getDefense();

 

System.out.println(" ==================== ");

System.out.println("체력은 : " + returnHp);

System.out.println("공격력은 : " + returnPoewr);

System.out.println("레벨은 : " + returnLevel);

System.out.println("방어력은 : " + retuDefense);

 

} // end of main

 

} // end of class

결과

잘못 입력하였습니다.

====================

체력은 : 0

공격력은 : 1000

레벨은 : 501

방어력은 : 0.0