캡슐화는 일반적으로 변수와 클래스를 하나로 묶는 작업이다
또한 접근 제어자를 이용하여 외부로부터 데이터를 보호하고 내부적으로만 사용되는 부분을 감추기 위한 개념으로 은닉화라고도 한다
Time t = new Time();
t.hour = 25; // 멤버변수에 직접 접근
class Time {
// 접근 제어자를 private로 하여 외부에서 직접 접근 방지
private int hour;
private int min;
private int sec;
// 간접 접근 허용
public int getHour() {
return hour;
}
public void setHour() {
if (hour < 0 || hour > 23)
return;
this.hour = hour;
}
}
private으로 캡슐화된 멤버는 직접 접근할 수 없으므로 간접 접근을 해야 하며 이 때 사용되는 함수가
getter, setter 함수이다
getter와 setter를 사용하면 재사용을 위한 캡슐화가 가능한 이점이 있다
외부에서 객체의 데이터를 읽을 때 사용하는 메서드
get
을 붙이고 반환받을 멤버변수의 이름 혹은 해당 변수를 직관적으로 표현하는 단어가 와야 한다public int getHour() {}
외부에서 메서드를 통해 데이터에 접근하도록 하는 메서드
set
을 붙이고 수정할 멤버변수의 이름 혹은 해당 변수를 직관적으로 표현하는 단어가 와야 한다public void setHour() {}
클래스와 클래스의 멤버에 부가적인 의미 부여
접근 제어자 : public
, protected
, (default)
, private
그 외 : static
, final
, abstract
, native
, transient
, synchronized
, volatile
, strictfp
class ModifierTest {
public static final int WIDTH = 200;
}
하나의 대상에 여러 제어자를 같이 사용가능 (접근 제어자는 하나만)
접근 제어자는 클래스의 멤버(변수, 메서드)들의 접근 권한을 지정한다.
class A {
public String y(){
return "public void y()";
}
private String z(){
return "public void z()";
}
public String x(){
return z();
}
}
public class AccessDemo1{
public static void main(String[] args){
A a = new A();
System.out.println(a.y());
System.out.println(a.z()); // 메서드 z에 접근 불가
System.out.println(a.x());
}
}
접근 제어자 | 같은 클래스 | 같은 패키지 | 자식 클래스 | 그 외의 영역 |
---|---|---|---|---|
public | O | O | O | O |
protected | O | O | O | X |
default | O | O | X | X |
private | O | X | X | X |
public class Everywhere {
public String var = "누구든지 허용"; // public 필드
public String getVar() { // public 메소드
return this.var;
}
}
public 접근 제어자는 프로그램 어디서나 직접 접근할 수 있다
또한 private 멤버와 프로그램에 접근할 수 있게 하는 역할을 수행한다
public class SameClass {
private String var = "같은 클래스만 허용"; // private 필드
private String getVar() { // private 메소드
return this.var;
}
}
private 접근 제어자를 사용하여 선언된 클래스 멤버는 외부에 공개되지 않으며 외부에서 접근할 수 없다
해당 객체의 public 메서드를 통해서만 접근할 수 있으며 클래스 내부의 세부적인 동작을 구현하는 데 사용한다
// 같은 패키지만 접근 허용
package test;
public class SamePackage {
String sameVar = "같은 패키지는 허용"; // default 필드
}
// 같은 클래스도 접근 허용
package test;
public class SameClass {
String var = "다른 패키지는 접근 불가"; // default 필드
public static void main(String[] args) {
SamePackage sp = new SamePackage();
System.out.println(sp.sameVar); // 같은 패키지는 허용
}
}
default 접근 제어자는 클래스, 클래스 멤버 접근 제어의 기본값으로 접근 제어자가 지정되지 않으면 자동적으로 설정된다
default 접근 제어를 가지는 멤버는 같은 클래스의 멤버와 같은 패키지에 속하는 멤버에서만 접근할 수 있다
// 같은 패키지는 접근 허용
package test;
public class SameClass {
protected String sameVar = "다른 패키지에 속하는 자식 클래스까지 허용"; // protected 필드
}
// 다른 패키지에 속하는 자식 클래스도 접근 허용
package test.other;
import test.SameClass; // test 패키지의 SameClass 클래스를 불러들여 포함시킴.
public class ChildClass extends SameClass {
public static void main(String[] args) {
SameClass = new SameClass();
System.out.println(sp.sameVar); // 다른 패키지에 속하는 자식 클래스까지 허용
}
}
protected 멤버는 부모 클래스에 대해서는 public 멤버, 외부에서는 private 멤버처럼 취급된다.
1. 이 멤버를 선언한 클래스의 멤버
2. 이 멤버를 선언한 클래스가 속한 패키지의 멤버
3. 이 멤버를 선언한 클래스를 상속받은 자식 클래스의 멤버
클래스의, 공통적인 의미를 갖는다
class StaticTest {
// 클래스 변수
static int width = 200;
static int height = 100;
// 클래스 초기화 블럭
// static 변수의 복잡한 초기화 수행
static {}
// 클래스 메서드
static int max(int a, int b) {
return a > b ? a : b;
}
}
변경될 수 없는 멤버를 만들 때 사용한다
final
이 붙으면 값을 변경할 수 없는 상수가 된다// 조상이 될 수 없는 클래스
class FinalTest {
// 상수 멤버변수
final int MAX_SIZE = 10;
// 변경 불가능한 메서드 (오버라이딩 불가)
final void getMaxSize() {
// 상수 지역변수
final int LV = MAX_SIZE;
}
}
추상적인 의미를 가지는 제어자로 객체지향개념인 추상화를 활용할 때 사용한다
// 추상 클래스 (추상 메서드를 포함한 클래스)
abstract class AbsractTest {
// 추상 메서드 (구현부가 없는 메서드)
abstract void move();
}
AbstractTest a = new AbstractTest(); // 에러, 추상 클래스의 인스턴스 생성 불가