[JAVA] 객체지향 프로그래밍(OOP) - 캡슐화

2022. 9. 7. 19:56

캡슐화(Encapsulation)

특정 객체 안에 관련된 속성과 기능을 하나의 캡슐(capsule)로 만들어 데이터를 보호하는 것

캡슐화는 데이터를 보호하는 목적으로 만들어졌다. 즉, 캡슐화는 정보 은닉이라고 정리할 수 있다.

자바는 캡슐화의 수단으로 접근제어자로 데이터를 보호, 은닉하고 getter와 setter 메서드를 사용해서 data에 접근한다.

 


1. 접근제어자

접근제어자는 멤버나 클래스에 사용하고 외부에서 접근하지 못하도록 제한한다.

 

접근제어자는 클래스, 멤버변수, 메서드, 생성자에 사용된다.

private     : 같은 클래스 내에서만 접근 가능
default     : 같은 패키지 내에서 접근 가능
protected : 같은 패키지, 다른 패키지의 하위 클래스에서 접근 가능
public      : 모든 곳에서 접근 가능

 

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

1. 외부로부터 데이터를 보호할 수 있다. 

2. 외부에는 불필요한 부분을 감출 수 있다.

 

package encap;

//encap.Parent
public class Parent {
    private int a = 1;
    int b = 2;
    protected int c = 3;
    public int d = 4;

    public void print(){
        System.out.println(a); //1
        System.out.println(b); //2
        System.out.println(c); //3
        System.out.println(d); //4
    }
}

class Test {
    public static void main(String[] args) {
        Parent p = new Parent();

        p.print();

//        System.out.println(p.a); //에러!!
        System.out.println(p.b); //2
        System.out.println(p.c); //3
        System.out.println(p.d); //4
    }
}

위와 같이 Parent 클래스 안에서 a, b, c, d를 출력하면 문제없이 다 출력이 된다. 하지만 다른 클래스에서는 private에 접근하지 못하고 에러가 발생한다.

 

이번엔 다른 패키지를 만들어서 Parent의 멤버에 접근해보자.

package anotherencap;

import encap.Parent;

//anothercap.Child
public class Child extends Parent {
    public void print() {
//        System.out.println(a); //같은 클래스에서만 가능
//        System.out.println(b); //같은 패키지 내에서만 가능
        System.out.println(c); //3 다른 패키지의 하위 클래스에서 호출
        System.out.println(d); //4
    }
}

class Test {
    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);
    }
}

위처럼 Parent 클래스를 상속받은 Child 클래스에서는 protected 접근 제어자부터 접근이 가능하고 Test 클래스에서는 public 접근 제어자만 접근이 가능하다. 

 

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

 

2. Getter/Setter

접근 제어자를 사용하여 데이터를 보호하고 은닉한다고 했다. 

캡슐화를 하면서 데이터의 변경이 필요할 땐 어떻게 해야할까?

 

getter와 setter 메서드를 사용하면 된다.

일반적으로 getter와 setter의 메서드 이름은 get or set + 멤버 변수로 정의한다.

 

getter : 데이터의 값을 가져올 수 있는 메서드
setter : 외부에서 접근하여 데이터의 값을 변경하는 메서드

 

x와 y를 멤버 변수로 갖는 Coordinate 클래스를 작성하고 외부에서 x와 y의 값을 변경해보자.

class Coordinate {
    private int x;
    private int y;

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }
}


public class CoordinatesTest {
    public static void main(String[] args) {
        Coordinate c = new Coordinate();
        System.out.println("(" + c.getX() + ", " + c.getY() + ")"); //(0, 0)

        c.setX(5);
        c.setY(4);

        System.out.println("(" + c.getX() + ", " + c.getY() + ")"); //(5, 4)
    }
}

실행해보면 getX, getY 메서드로 Coordinate에 private 접근제어자로 지정된 멤버 변수에 접근해 값을 읽어올 수 있고 setX, setY 메서드로 인스턴스의 x, y 값을 변경할 수 있다. 

 

정리하면 접근 제어자로 데이터를 보호, 은닉해서 캡슐화가 가능하게 되고 getter와 setter로 값에 접근하고 변경할 수 있다.

 

 

BELATED ARTICLES

more