The Debugging Chronicles : "코드의 미학"

객체 지향 언어 특징 - 캡슐화(Encapsulation) 본문

JAVA/자바 수업 내용

객체 지향 언어 특징 - 캡슐화(Encapsulation)

sweetseonah1004 2024. 7. 12. 11:42

 

객체지향 언어의 특징

상속성
다형성
캡슐화
추상화

캡슐화

위키 백과를 살펴보면 다음과 같이 적혀있다.

 

소프트웨어 시스템에서 캡슐환는 데이터를 데이터에서  작동하는 메커니즘이나 메서드와 묶는 것을 말합니다.
또한 객체의 구성 요소와 같은 일부 데이터에 대한 직접 액세스를 제한하는 것을 의미할 수도 있습니다.
본질적으로 캡슐화는 외부 코드가 객체의 내부 작동과 관련되지 않도록 방지합니다.

 

객체 지향 프로그램이 언어 및 기타 관련 분야에서 캡슐화는 두가지 관련되지만 구별 되는 개념 중 하나를 의미하며 때로는 두가지 조합을 의미합니다.
- 객체의 일부 구성요소에 대한 직접 액세스를 제한하기 위한 언어 메커니즘
- 데이터와 해당 데이터에서 작동하는 메서드(또는 기타 기능) 의 번들링을 용이하게 하는 언어 구조

 


좀 더 풀어서 예제와 함께 캡슐화에 대해서 이해 해보자.

 

자바에서는 기능 단위별, 예를 들면 클래스 별로 보관하는 자바의 특성이 있다. 이를 모듈화, 컴포넌트화라고 하는데

위와 같은 특성 때문에 구현에 필요한 기능이 있다면 이미 만들어진 것들을 가져와서 사용하면 된다. 

 

예를 들면 Scanner를 가져다 쓴다고 해보자

 

Scanner 안에 클래스, 패키지, 코드덩어리들…. 내용은 몰라도 “사용방법(용법, 언제쓰는지)”만 알면 쉽게 가져다가 사용할 수 있다

 

마치 알약에서 내부에 무엇이 들어가 있는지 모르지만 여러가지 성분이 들어가 있는 것을 안다. 또한 알약의 용도,그리고 섭취 방법에 대해 알고 있다. 어떠한 물리적인 방법에 의해 효능이 있는지 모르지만 알약 껍질에 의해 내용물과는 물리적으로 접근할 수 없지만 제시간에 물과 함께 섭취하면 끝이다.

 

자바의 캡슐화도 이와 비슷하다.

알약 껍질처럼 외부 접근에 대한 차단이 있고 

차당 방법은 접근 제어자를 사용한다.

 

public / protected / default / private 이다.

 

이러한 캡슐화의 장점으로는 정보 은닉이 있다.

 

내가 개발한 내용을 상대방이 몰라도 쓸수 있게 묶어서 배포가 가능한것이다.

그래서 함수명이 쉬워야하고, 인자와 아웃풋이 그럴듯해야함!

 

int plus(int[] datas)

boolean isEmpty(int[] datas, int int)

 

메서드 시그니쳐만 보고도 다른 사람들이 쉽게 이해할수 있어야한다.

 

나만 아는 단어 도 안되고 너무 줄여도서 사용해도 안되다.

 

그렇기 때문에 설계시 input 과 output을 정확히 설계하는 것이 너무나도 중요하다.


자 이제 예제를 통해 코드내에서 캡슐화할 수 있는지 알아보겠다.

 

예제를 먼저 보자

package class01;

class Student{
	// 클래스 외부에서 멤버변수에 접근하는 것을 막아야함~~
	// JAVA 공개정책
	// "접근 제어자"를 사용해서 공개범위를 변경
	private int num;
	private String name;
	private int score;
	// private == 클래스 외부에서 접근할 수 없다!!
	// 모든 멤버변수에 pirvate 을 반드시 추가해주세요!
	Student(int num, String name){
		this.num = num;
		this.name = name;
		this.score = 50;
	}
//	private 된 멤버변수의 값을 변경하려면
//	반드시 메서드를 거쳐야한다!!
//
//	멤버변수에 값을 넣어야할때는 set멤버변수명 ()
//	멤버변수의 값을 받아올때에는 get멤버변수명 ()
    // 게터 세터
	//getter setter
    void setNum(int num) {
		this.num = num;
	}
	int getNum() {
		return this.num;
	}
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return this.num + "번 학생"+this.name + "은 " +this.score;
	}
	//코드내에서 어디서지 호출될 수 있어야함!!
	// public
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getScore() {
		return score;
	}
	public void setScore(int score) {
		this.score = score;
	}
	
}

public class Test01 {
	public static void main(String[] args) {
		Student stu1 = new Student(1001,"홍길동");
		
		// 재시험 등으로 점수가 변경되어야할때?
	
		
        stu1.score = 100; //<- 오류 발생!!! 
        stu1.setScore(100);
        // 개발자가 임의로 데이터값을 언제든지 수정할 수 있다는 뜻
		
		System.out.println(stu1);
		
		
		
	}
}

 

첫 번째로 살펴 봐야할 것은 접근 제한자이다.

public 은 접근 제한을 하지 않고

private은 동일 클래스 내에서만 접근가능하다는 점이다.

 

이때 private으로 접근 제한된 멤버변수의 값을 변경하려면 반드시 메서드를 거쳐야한다.

 setter/ getter를 사용해야한다.

 

만약 객체를 호출하여 멤버변수에 접근할시 오류가 난다. 

반드시 setter인 setScore로 데이터 값에 접근해야한다.

 

package class02;

class Shape { // abstract 추상 클래스
   private String name;
   protected double area;
   Shape(String name){
      this.name=name;
      this.area=0.0;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
   public double getArea() {
      return area;
   }
   public void setArea(double area) {
      this.area = area;
   }
   @Override
   public String toString() {
      return this.name+"의 넓이 : "+this.area;
   }
}

class Circle extends Shape {
   private int radius;
   static final double PI=3.14;
   Circle(int radius){
      super("원");
      this.radius=radius;
      this.area=this.radius*this.radius*Circle.PI;
   }
   public int getRadius() {
      return radius;
   }
   public void setRadius(int radius) {
      this.radius = radius;
   }
}

public class Test01 {
   public static void main(String[] args) {

      //Shape s=new Shape("모양");
      // 추상 클래스로는 객체화(인스턴스화) 할 수 없음!!!
      // 객체를 생성하려고 존재하는게 아니라,
      // 클래스들을 정의하려고 존재하기때문에!!!!!
      //  == 클래스들의 틀

   }
}

 

다음은 접근 제한자 protected  개념이다.

동일한 패키지 내에서와 상속 관계에 있는 클래스만 접근 가능하다.

 

예제에서 다루지 않았지만 default는 동일 패키지 내에서만 접근이 가능하다.