Notice
Recent Posts
Recent Comments
Link
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

랩터

[Java] 캡슐화,패키지,접근제어자,getter와 setter 본문

공부/JAVA

[Java] 캡슐화,패키지,접근제어자,getter와 setter

raptorhs 2024. 6. 29. 16:00

캡슐화

캡슐화특정 객체 안에 관련된 속성과 기능을 하나의 캡슐(capsule)로 만들어 데이터를 외부로부터 보호하는 것을 말합니다. 이렇게 캡슐화를 해야 하는 이유로 크게 두 가지 목적이 있습니다. 첫째는 데이터 보호의 목적이고, 둘째로 내부적으로만 사용되는 데이터에 대한 불필요한 외부 노출을 방지하기 위함입니다.

자바에서 캡슐화를 수행하기 위한 핵심적인 수단으로 접근제어자(Access Modifier)와 getter와 setter 메서드를 중심으로 사용합니다.

 

패키지

패키지(package)란 특정한 목적을 공유하는 클래스와 인터페이스의 묶음을 의미합니다. 패키지는 클래스들을 그룹 단위로 묶어 효과적으로 관리하기 위한 목적을 가지고 있습니다.  패키지가 있는 경우 소스 코드의 첫 번째 줄에 반드시 package 패키지명이 표시되어야 하고, 만약 패키지 선언이 없으면 이름 없는 패키지에 속하게 됩니다.

 

pack.Data

package pack;

public class Data {
    public Data(){
        System.out.println("패키지 pack Data 생성");
    }
}

 

pack.a.User

package pack.a;

public class User {
    public User(){
        System.out.println("패키지 pack.a 회원 생성");
    }
}

 

  • 생성자에 public 을 사용했다. 다른 패키지에서 이 클래스의 생성자를 호출하려면 public 을 사용해야 한다

pack.PackageMain1

package pack;

public class PackageMain1 {
    public static void main(String[] args) {
        Data data =new Data();
        pack.a.User user = new pack.a.User();
    }
}
  • 사용자와 같은 위치: PackageMain1 과 Data 는 같은 pack 이라는 패키지에 소속되어 있다. 이렇게 같은 패키 지에 있는 경우에는 패키지 경로를 생략해도 된다.
  • 사용자와 다른 위치: PackageMain1 과 User 는 서로 다른 패키지다. 이렇게 패키지가 다르면 pack.a.User 와 같이 패키지 전체 경로를 포함해서 클래스를 적어주어야 한다.

패키지 - import

import

이전에 본 코드와 같이 패키지가 다르다고 pack.a.User 와 같이 항상 전체 경로를 적어주는 것은 불편하다. 이때는 import 를 사용하면 된다.

package pack;
import pack.a.User;
public class PackageMain2 {
 public static void main(String[] args) {
 Data data = new Data();
 User user = new User(); //import 사용으로 패키지 명 생략 가능
 }
}

 

접근 제어자

제어자(Modifier)

자바 프로그래밍에서 제어자는 클래스, 필드, 메서드, 생성자 등에 부가적인 의미를 부여하는 키워드를 의미합니다.

자바에서 제어자는 크게 접근 제어자기타 제어자로 구분할 수 있습니다.

  • 접근제어자: public,protected,(default),private
  • 기타제어자:static,final,abstract 등

각 대상에 대해서 접근 제어자는 단 한 번만 사용할 수 있습니다. 접근 제어자를 사용하면 클래스 외부로의 불필요한 데이터 노출을 방지(data hiding)할 수 있고, 외부로부터 데이터가 임의로 변경되지 않도록 막을 수 있습니다.

 

접근 제어자                접근 제한 범위

private 동일 클래스에서만 접근 가능
default 동일 패키지 내에서만 접근 가능
protected 동일 패키지 + 다른 패키지의 하위 클래스에서 접근 가능
public 접근 제한 없음

 

위의 내용을 접근 제한 범위에 따라서 표현하면,

public(접근 제한 없음) > protected(동일 패키지 + 하위클래스) > default(동일 패키지) > private(동일 클래스) 순으로 정리할 수 있습니다.

 

package package1;

class Test{ // Test클래스의 접근 제어자는 default(동일 패키지)내에서 접근 가능
    public static void main(String[] args) {
        Parent p = new Parent();
        // System.out.println(p.a); //동일 클래스가 아니기 때문에 에러발생
        System.out.println(p.b);
        System.out.println(p.c);
        System.out.println(p.d);
    }
}
public class Parent {// Parent 클래스의 접근제어자는 public(접근 제한 없음)
    private int a =1;
    int b = 2;
    protected int c = 3;
    public int d =4;
    public void printEach(){ // 동일 클래스이기 때문에 에러발생하지 않음
        System.out.println(a);
        System.out.println(b);
        System.out.println(c);
        System.out.println(d);

    }
}

Test클래스에서 객체를 생성하여 접근을 시도했을 때는 private접근 제어자가 있는 a에는접근이 불가하여 에러가 발생한다.

package package2;
import package1.Parent;
class Child extends package1.Parent { // package1으로부터 Parent 클래스를 상속
    public void printEach(){
//        System.out.println(a); // 에러 발생
//        System.out.println(b);
        System.out.println(c);// 다른 패키지의 하위 클래스
        System.out.println(d);
    }
}
public class Test2 {
    public static void main(String[] args) {
        Parent p =new Parent();
//        System.out.println(p.a); // punlic을 제외한 모든 호출 에러!
//        System.out.println(p.b);
//        System.out.println(p.c);
        System.out.println(p.d);
    }
}

 

 

접근 제어자를 통해 외부로부터 데이터를 보호하고, 불필요하게 데이터가 노출되는 것을 방지할 수 있습니다.

 

 

package access.ex;

public class CounterMain {
    public static void main(String[] args) {
        MaxCounter counter = new MaxCounter(3);
        counter.increment();
        counter.increment();
        counter.increment();
        counter.increment();
        int count = counter.getCount();
        System.out.println(count);
    }
}

 

package access.ex;

public class MaxCounter {
    private int count = 0;
    private int max;

    public MaxCounter(int max) {
        this.max = max;
    }

    public void increment(){
        if(count>=max){
            System.out.println("최대값을 초과할수 없습니다");
            return;
        }
        count++;
    }
    public int getCount(){
        return count;
    }
}

 

 

 

package access.ex;

public class ShoppingCartMain {
    public static void main(String[] args) {
        ShoppingCart cart = new ShoppingCart();

        Item item1 = new Item("마늘",2000,2);
        Item item2 = new Item("상추",3000,4);

        cart.addItem(item1);
        cart.addItem(item2);

        cart.displayItems();
    }
}

 

package access.ex;

public class Item {
    private String name;
    private int price;
    private int quantity;

    public Item(String name, int price, int quantity) {
        this.name = name;
        this.price = price;
        this.quantity = quantity;
    }

    public String getName(){
        return name;
    }
    public int getTotalPrice(){
        return price * quantity;
    }
}

 

package access.ex;

public class ShoppingCart {
    private Item[] items = new Item[10];
    private int itemCount;

    public void addItem(Item item){
        if(itemCount >= items.length){
            System.out.println("장바구니가 가득 찼습니다.");
            return;
        }
        items[itemCount] = item;
        itemCount++;
    }

    public void displayItems(){
        System.out.println("장바구니 상품 출력");
        for (int i=0; i< itemCount; i++){
            Item item = items[i];
            System.out.println("상품명:" + item.getName() + ", 합계:" + item.getTotalPrice());
        }
        System.out.println("전체 가격 합:" + calculateTotalPrice());
    }

    private int calculateTotalPrice(){
        int totalPrice = 0;
        for (int i =0; i<itemCount; i++){
            Item item = items[i];
            totalPrice += item.getTotalPrice();
        }
        return totalPrice;
    }
}

 

 

getter와 setter 메서드

앞서 우리는 자바에서 데이터 보호와 은닉을 위한 효과적인 방법으로 접근 제어자를 사용한다는 것을 학습했습니다.

private접근 제어자가 포함되어 있는 객체의 변수의 데이터 값을 추가하거나 수정하고 싶을 때, getter와 setter메서드를 사용하면 됩니다.

 

public class GetterSetterTest {
    public static void main(String[] args) {
        Worker w = new Worker();
        w.setName("김코딩");
        w.setAge(30);
        w.setId(5);

        String name = w.getName();
        System.out.println("근로자의 이름은 "+ name);
        int age = w.getAge();
        System.out.println("근로자의 나이는 " + age);
        int id = w.getId();
        System.out.println("근로자의 나이는 " + id);
    }
}
class Worker{
    private String name;
    private int age;
    private int id;

    public String getName(){//멤버변수의 값
        return name;
    }
    public void setName(String name){ // 멤버변수의 값 변경
        this.name = name;
    }
    public int getAge(){
        return age;
    }
    public void setAge(int age){
        if(age<1) return;
        this.age = age;
    }
    public int getId(){
        return id;
    }
    public void setId(int id){
        this.id = id;
    }
}

 

setter메서드는 외부에서 메서드에 접근하여 조건에 맞을 경우 데이터 값을 변경할 수 있게 해주고 일반적으로 메서드명에 set-을 붙여서 정의합니다.

getter메서드는 이렇게 설정한 변수값을 읽어오는데 사용하는 메서드입니다.

 

w의 setter 메서드를 사용하여 이름, 나이, 아이디에 대한 데이터값을 저장하고, getter 메서드를 통해 해당 데이터 값을 불러와 변수에 담아 출력해 주고 있습니다.

이렇게 setter와 getter 메서드를 활용하면 데이터를 효과적으로 보호하면서도 의도하는 값으로 값을 변경하여 캡슐화를 보다 효과적으로 달성할 수 있습니다.

'공부 > JAVA' 카테고리의 다른 글

[Java] 다형성  (0) 2024.07.02
[Java] 추상화  (0) 2024.06.29
[Java] 상속(Inheritance)  (0) 2024.06.28
[Java] 내부 클래스  (0) 2024.06.26
[Java] 필드와 메서드  (0) 2024.06.26