Backend/JAVA

[JAVA] JAVA 프로그래밍 기초 교육 : 엑세스 한정자 & 캡슐화

JOKUN 2022. 5. 25. 17:17

교재 : JAVA 프로그래밍 기초 - 12. 엑세스 한정자와 캡슐화

+ 자바의 정석 [기초편]

 

# 한정자(접근 제어자 = 엑세스 수식자)

멤버 또는 클래스에 사용.

해당하는 멤버/클래스를 외부에서 접근하지 못하도록 제한함

 

[접근 제어자를 사용하는 이유]

- 외부로부터 데이터를 보호하기 위해

- 외부에는 불필요한, 내부적으로만 사용되는 부분을 감추기 위해 (데이터 감추기(data hiding)) ▷ 캡슐화

 

접근 제어자가 사용될 수 있는 곳 : 클래스, 멤버변수, 메소드, 생성자
접근 제어자(한정자) 접근 가능 범위
private 같은 클래스 내 
기본  값(default) - 한정자 없음 같은 클래스
protected 같은 패키지 내, 그리고 다른 패키지의 자손 클래스에서 접근 가능
public 접근 제한 없음(어디서든 가능)

public(접근 제한 없음) > protected(같은 패키지+자손) > (default)(같은 패키지) > private(같은 클래스)

 

 

 

· private 멤버

public class 클래스명 {
    private 필드변수(멤버변수)선언;
    ...
    private 메소드정의;
    ...
}

· public 메소드

public class 클래스명 {
    private 멤버변수(필드변수);
    ...
    public 메소드정의
    ...
}

 

 

#캡슐화

캡슐화 : 보호하고 싶은 멤버에 'private'을 붙여 자유롭게 엑세스 할 수 없게 하는 구조

캡슐화의 장·단점
장점 단점
01. pricate 수식자를 이용해 외부로부터 데이터를 보호한다. 01. 소스 코드의 기술량이 증가한다.
02. 전용 엑세서 메소드를 이용하여(getter,setter) 
      외부로부터 잘못된 엑세스를 방지한다.
02. 내부 구조를 모르면 수정하기가 어렵다.
03. 사용자가 내부 구조를 이해하지 않아도 사용할 수 있다. 03. 숙련자가 아닌 사람이 만든 클래스의 경우
      신용성이 부족하다.

 

 

 

 

#  엑세서 메소드 겟터(getter)와 셋터(setter)

 

· getter 메소드

  - 멤버 변수(필드 변수)의 값을 반환한다. (멤버 변수의 값을 읽음)

get멤버변수명

· setter 메소드

  - 인수(매개변수)에 지정된 값을 검사하여 조건에 맞는 값일 때만 멤버 변수(필드 변수)의 값을 변경하도록 작성된다.

   (멤버 변수의 값을 변경함)

set멤버변수명

 

보호하고 싶은 멤버를 private나 protected로 제한하고 

get/set 메소드 앞에 public 수식자를 붙여 간접적으로 멤버 변수의 값을 다룰 수 있도록 한다.

public 리턴값형 get<필드변수명>()

public void set<필드변수명>(인수)

* 'get/set 필드 변수명'에서 필드 변수명은 JavaBeans의 규칙에 따라 선두 문자를 대문자로 표기한다.

* 필드 변수의 형태가 boolean의 경우에는 get___대신에 is ___라고 기술하는 규칙도 있다.

 

 

 

 

 

[예제] public 메소드를 사용하여 클래스 내 private 필드 변수에 값 설정하기

class Computer3 {
    private String os;
    private int memory;

    public void show() { // public메소드show
        System.out.println("PC의 OS는 " + os + "입니다.");
        System.out.println("메모리는 " + memory + "GB입니다.");
    }

    public void setOsMemory(String os, int memory) { // public메소드 setOsMemory
        // 설정할 메모리값이 정산인지 확인
        if (memory > 0) {
            // 정상적인 인수값을 필드변수로 설정
            this.os = os;
            this.memory = memory;
            System.out.println("OS를 " + os + "로 메모리를 " + memory + "GB로 변경했습니다. ");
        } else {
            System.out.println("「" + memory + "」는 올바른 메모리크기가 아닙니다.");
        }
    }
}

public class PublicMember {
    public static void main(String[] args) {
        Computer3 com = new Computer3();

        // 다른 클래스의 private변수는 접근할 수 없습니다.
        // com.os = "Windows 11"; // 주석처리
        // com.memory = -5445; // 주석처리

        // 올바른 값을 공식연산을 호출 설정
        com.setOsMemory("Windows 11", 32); // public메소드setOsMemory호출하여 값 설정
        com.show(); // public메소드 show호출

        // 잘못된 값 설정
        System.out.println("\n메모리에 잘못된 값(-5445)를 지정해 봅니다.");
        com.setOsMemory("Windows 10", -5445);
        com.show();
    }
}

▽ 실행 화면 ▽

 

 

 


 

 

 

[연습문제]

더보기

12-5. 연습문제

<질문1> 다음의 질문  ①~⑤에 대해 ○인가×로 대답하십시오.

① 액세스 제한의 패턴은 「public」, 「디폴트」, 「private」의 3개가 있다.
② private 수식자는 외부로부터의 액세스를 불가능하게 한다. O
③ 액세스 수식자는 클래스 내의 멤버에게만 설정할 수 있다. X
④ 캡슐화란 필드 변수를 private로 설정하여 액세스 불가능하게 한 클래스를 말한다. X
⑤ 액세서 메소드란 값을 설정하는 세터 메소드와 값을 취득하는 게터 메소드의 총칭이다. O

 

<질문2> 아래 액세스 한정자의 제한이 강한 순서대로 나열해 보세요.

액세스 한정자
① protected
② 기본값
③ private
④ public

3 > 2 > 1 > 4

<질문 3> 아래의 캡슐화된 소스코드를 보고 오류 3개를 찾으시오.

① 소스폴더: javabasic/src
② 패키지: chap12exercise
③ 이름: Dog
package chap12Excercise;

public class Dog {
    String name;

    public String getname() {
        return this.name;
    }

    void setName(String name) {
        this.name = name;
    }
}

 

1. 필드변수에 private으로 안걸어놨음

2. gettet메소드에서 Name 첫글자가 대문자임

3. stter메소드에 접근한정자가 선언되지 않음 - public

 

<질문4> 아래에 표시된 Books1 클래스를 캡슐화하십시오.

힌트

  • 필드 변수의 private 정의함
  • 각 필드 변수에 해당하는 접근자 메서드 정의함
① 소스폴더: javabasic/src
② 패키지: chap12exercise
③ 이름: Books1
package chap12Excercise;

public class Books1 {
    String title;

    int price;

    void show() {
        System.out.println("이 책의 제목은 " + this.title + "이고 가격은 " + this.price+ "원입니다.");
    }
}

답 : 아래 문제와 합쳐서 풀이

 

 

<질문5> 질문 4에서 캡슐화한 클래스 Books1.java에서, 부정한 값을 막는 처리를 추가한 Books2.java를 작성하십시오.

변경 사양

가격에 대해 부의 값이 입력되었을 경우는 「0」을 설정하는 처리를 price의 세터 메소드에 추가한다.
잘못된 값의 경우, 다음 메시지가 화면에 출력됩니다.
“설정하는 값이 -X이기 때문에, 가격은 0을 설정했습니다.”
참고로 -X는 인수의 값을 출력하기 때문에 그 때마다 바뀝니다.

package jokun.chap12;

public class Books2 {

    private String title;
    private int price;

      public void show() {
        System.out.println("이 책의 제목은 " + this.title + "이고 가격은 " + this.price+ "원입니다.");
    }

    public String getTitle(){
        return this.title;
    }

    public int getPrice(){
          return this.price;
    }

       public void setTitle(String title) {
        this.title = title;
    }
    public void setPrice(int price) {
        if (price < 0){
            this.price = 0;
            System.out.println("설정하는 값이 " + price + "이기 때문에, 가격은 0을 설정했습니다.");
        }else{
            this.price = price;
        }
    }
}

 

 

<질문6> 아래 실행 결과가 되는 Practice1201.java의 main 메소드의 처리를 작성해 주세요. Practice1201.java에서는 <문제5>에서 만든 Books2 클래스를 복사하여 Books3 클래스를 정의합니다.

main 메소드의 처리 사양
① Books3 객체를 2개 생성한다.
② 첫 번째 오브젝트에 타이틀 “Java 입문”, 가격 25000을 설정한다.
③ ②의 결과를 화면에 표시하는 show 메소드를 호출한다.
④ 두 번째 객체에 타이틀 “Java 기본” , 가격 -38000을 설정한다.
⑤ ④의 결과를 화면에 표시하는 show 메소드를 호출한다.
※②④의 값의 설정에는 각 세터 메소드를 이용한다.

① 소스 폴더: javabasic/src
② 패키지: chap12exercise
③ 이름: Practice1201
package chap12Excercise;

class Books3 {
    private String title;
    private int price;

    public void show() {
        System.out.println("이 책의 제목은 " + this.title + "이고 가격은 " + this.price + "원입니다.");
    }

    public String getTitle() {
        return this.title;
    }

    public int getPrice() {
        return this.price;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public void setPrice(int price) {
        if (price < 0) {
            this.price = 0;
            System.out.println("설정한 값이 " + price + "이므로 가격은 0이 설정됩니다.");
        } else {
            this.price = price;
        }
    }
}

public class Practice0301 {
    public static void main(String[] args) {
        // Books3객체 2개 생성
        ①처리사양 여기에 기술

        // book1객체의 값설정 및 결과 표시
        ②와 ③ 처리사양을 여기에 기술

        // book2객체의 값설정(가격은 잘못된 값과 결과를 표시함)
        ④와 ⑤ 처리사양을 여기에 기술

    }
}

 

package jokun.chap12;

class Books3 {
    private String title;
    private int price;

    public void show() {
        System.out.println("이 책의 제목은 " + this.title + "이고 가격은 " + this.price + "원입니다.");
    }

    public String getTitle() {
        return this.title;
    }

    public int getPrice() {
        return this.price;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public void setPrice(int price) {
        if (price < 0) {
            this.price = 0;
            System.out.println("설정한 값이 " + price + "이므로 가격은 0이 설정됩니다.");
        } else {
            this.price = price;
        }
    }
}


public class Practice1201 {
    public static void main(String[] args) {
        // Books3객체 2개 생성
        Books3 book1 = new Books3();
        Books3 book2 = new Books3();

        book1.setTitle("Java 입문");
        book1.setPrice(25000);
        book1.show();

        book2.setTitle("JAva 기본");
        book2.setPrice(-38000);
        book2.show();

    }
}