하얀성 2023. 10. 1. 20:35

패키지와 패키지, 클래스와 클래스간 등의 클래스의 사용범위를 정하기 위해 접근 제어자가 있는거구나? 

네, 정확하게 이해하셨습니다! 접근 제어자는 클래스, 메서드, 필드의 사용 범위를 제한하여 객체 지향 프로그래밍의 중요한 원칙 중 하나인 캡슐화를 도와줍니다.



접근 제어자(Access Modifier):

클래스, 메서드, 필드의 접근 범위를 지정합니다.
public, protected, default, private 네 가지 접근 제어자가 있습니다.

 


public:
어떤 클래스에서라도 접근 가능합니다.
다른 패키지의 클래스에서도 접근할 수 있으므로 외부에 공개되어야 하는 클래스, 메서드, 필드에 사용합니다.

 

protected:
같은 패키지 내의 클래스나 상속 받은 클래스에서만 접근 가능합니다.

 

default (접근 제어자를 명시하지 않는 경우):
같은 패키지 내의 클래스에서만 접근 가능합니다.

 

private:
같은 클래스 내에서만 접근 가능합니다.
클래스의 내부 동작 방식을 숨기고 싶을 때 사용합니다.

 


캡슐화(Encapsulation):
객체의 상태를 나타내는 필드와 상태를 변경하는 메서드를 하나로 묶는 프로세스입니다.
캡슐화를 통해 객체의 내부 구현을 숨기고, 외부에서는 해당 객체의 메서드를 통해서만 상태를 변경할 수 있습니다.
이를 통해 코드의 안정성과 유지보수성이 향상됩니다.


import Statement:
다른 패키지의 클래스를 사용하기 위해 import를 사용합니다.
import를 사용하면 클래스의 전체 이름을 매번 쓰지 않아도 됩니다.

 


이러한 접근 제어자와 캡슐화의 원칙을 이용하여 코드의 구조와 설계를 잘 해야 프로그램의 유지 보수가 용이하고 오류 발생 가능성이 줄어듭니다.


< 접근제어자가 필요한 이유 >

 

아래의 코드처럼 계좌에 돈이 있는 경우,

따로 계좌 클래스를 보호하지 않으면 계좌의 액수를 다른 클래스로 조절하게 된다. 

public class Main {
  public static void main (String[] args) {
    // 1. 계좌 생성
    Account myAccount = new Account(1000000);
    System.out.println(myAccount.toString());
    
    // 2. 계좌 해킹
    Hacker.malcious(myAccount);
    
    // 3. 결과 출력
    System.out.println(myAccount.toString());
  }
}

class Account {
  // 필드
  int balance;

  // 생성자
  public Account(int balance) {
    this.balance = balance;
  }

  // 메소드
  public String toString() {
    return String.format("Account { balance: %d }", balance);
  }
}

class Hacker {
  // 클래스 메소드 - 계좌의 잔액을 0원으로 변경
  public static void malcious(Account account) {
    /* 1. 파라미터 계좌의 잔액을 0으로 변경하세요. */
    account.balance = 0;
  }
}

 


접근제어자 활용예시(필드의 변수와 메소드에 모두 사용가능)

 

class Account {
  public int number;       // 완전 공개 필드
  private String password; // 비공개 필드
  private int balance;     // 비공개 필드
  // 비공개 메소드 - 외부 호출 불가
  private void somthing() {}
}

 

접근제어자 수정으로 막아보기

(Theif 클래스의 steal 클래스 메소드가 객체를 들고와서 외부에서 접근하려했으나, private인 money에 접근 불가하게됨.)

public class Theif {
  // 메인 메소드
  public static void main(String[] args) {
    // 지갑 객체 생성
    Wallet wallet = new Wallet(30000);
    System.out.print(wallet.toString());
    
    // 지갑에서 돈을 모두 꺼냄
    Theif.steal(wallet);
    
    // 지갑 확인
    System.out.println(" -> " + wallet.toString());
  }
  
  // 클래스 메소드
  public static void steal(Wallet target) {
    target.money = 0;
  }
}

class Wallet {
  // 필드(인스턴스 변수)
  private int money; /* 1. 주어진 필드를 외부로부터 감추세요. */
  
  // 생성자
  public Wallet(int i) {
    money = i;
  }
  
  // 메소드
  public String toString() {
    return String.format("Wallet { money: %d }", money);
  }
}


출처: 그림으로 배우는 자바 객체지향.