[객체 지향 프로그래밍] 제어자(modifier)

sy·2023년 7월 2일
0

제어자(modifier)

제어자는 클래스, 변수 또는 메서드의 선언부에 함께 사용되어 부가적인 의미를 부여한다.

접근 제어자: public, protected, default, private
그 외: static, final, native, transient, synchronized, volatile, strictfp

제어자는 클래스나 멤버 변수와 메서드에 주로 사용되며 하나의 대상에 대해 여러 제어자를 조합하여 사용 가능하다. 단, 접근 제어자는 한 번에 네 가지 중 하나만 선택할 수 있다.

static

  • '클래스의' 또는 '공통적인'의 의미를 가지고 있다.
  • 클래스 변수(static 변수)는 인스턴스에 관계 없이 같은 값을 갖는다. 하나의 변수를 모든 인스턴스가 공유하기 때문이다.

static이 사용될 수 있는 곳 - 멤버변수, 메서드, 초기화 블럭

static 멤버 변수

  • 모든 인스턴스에 공통적으로 사용되는 클래스 변수가 된다.
  • 클래스 변수는 인스턴스를 생성하지 않고도 사용 가능하다.
  • 클래스가 메모리에 로드될 때 생성된다.

static 메서드

  • 인스턴스를 생성하지 않고도 호출이 가능한 static 메서드가 된다.
  • static 메서드 내에서는 인스턴스 멤버들을 직접 사용할 수 없다.

final

  • '마지막의' 또는 '변경할 수 없는'의 의미를 가지며 거의 모든 대상에 사용될 수 있다.

[final이 사용될 수 있는곳]

  • 클래스: 변경될 수 없는 클래스, 확장될 수 없는 클래스가 된다. 그래서 final로 지정된 클래스는 다른 클래스의 조상이 될 수 없다.
  • 메서드: 변경될 수 없는 메서드, final로 지정된 메서드는 오버라이딩을 통해 재정의 될 수 없다.
  • 멤버 변수, 지역 변수: 변수 앞에 final이 붙으면, 값을 변경할 수 없는 상수가 된다.
final class FinalTest { // 조상이 될 수 없는 클래스
	final int MAX_SIZE = 10; // 값을 변경할 수 없는 멤버 변수 (상수)
    
    final void getMaxSize() { // 오버라이딩 할 수 없는 메서드 (변경 불가)
    	final int LV = MAX_SIZE; // 값을 변경할 수 없는 지역 변수 (상수)
        return MAX_SIZE;
    }
}

인스턴스 변수의 경우 생성자에서 초기화 되도록 할 수 있다.

class Card {
	final int NUMBER; // 상수지만 선언과 함께 초기화 하지 않고 생성자에서 단 한 번 초기화 할 수 있다.
    
    Card(int num) {
    	NUMBER = num;
    }
}

abstract

'미완성'의 의미를 가진다. 메서드의 선언부만 작성하고 실제 수행 내용은 구현하지 않은 추상 메서드를 선언하는데 사용된다.

[abstract가 사용될 수 있는 곳]

  • 클래스: 클래스 내에 추상 메서드가 선언되어 있음을 의미한다.
  • 메서드: 선언부만 작성하고 구현부는 작성하지 않는 추상 메서드임을 알린다.

추상 클래스는 아직 완성되지 않은 메서드가 존재하는 미완성 설계도이므로 인스턴스를 생성할 수 없다.

abstract class AbstractTest { // 추상 클래스 (추상 메서드를 포함한 클래스)
	abstract void move(); // 추상 메서드 (구현부가 없는 메서드)
}

💡 드물지만 추상 메서드가 없는 완성된 클래스도 추상 클래스로 만드는 경우도 있다. (예를 들어, WindowAdapter) 이 클래스 자체로는 쓸모가 없지만, 다른 클래스가 이 클래스를 상속 받아서 일부의 원하는 메서드만 오버라이딩해도 된다는 장점이 있다.

접근 제어자 (access modifier)

제어자 같은 클래스 같은 패키지 자손 클래스 전체
public O O O O
protected O O O X
(default) O O X X
private O X X X

접근 제어자를 이용한 캡슐화

  • 클래스나 멤버, 주로 멤버에 접근 제어자를 사용하는 이유는 클래스의 내부에 선언된 데이터를 보호하기 위해서다.
  • 외부에서 접근할 필요가 없는 멤버들들 private으로 지정하여 외부에 노출시키지 않음으로써 복잡성을 줄일 수 있다.

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

  • 외부로부터 데이터를 보호하가 위해서
  • 외부에는 불필요한, 내부적으로만 사용되는 부분을 감추기 위해서

정리

[사용 가능한 제어자]

  • 클래스: public, (default), final, abstract
  • 메서드: 모든 접근 제어자, final, abstract, static
  • 멤버변수: 모든 접근 제어자, final, static
  • 지역변수: final

❗ 주의 사항

1. 메서드에 static과 abstract를 함께 사용할 수 없다.
-> static 메서드는 몸통이 있는 메서드에만 사용할 수 있다.

2. 클래스에 abstract와 final을 동시에 사용할 수 없다.
-> 클래스에 사용되는 final은 클래스를 확장할 수 없다는 의미이고 abstract는 상속을 통해서 완성되어야 한다는 의미이므로 서로 모순되기 때문이다.

3. abstract 메서드의 접근 제어자가 private일 수 없다.
-> abstract 메서드는 자손클래스에서 구현해주어야 하는데 접근 제어자가 pricate이면, 자손 클래스에서 접근할 수 없기 때문이다.

4. 메서드에 private과 final을 같이 사용할 필요는 없다.
-> 접근 제어자가 pricate인 메서드는 오버라이딩 될 수 없기 때문에 둘 중 하나만 사용해도 의미가 충분하다.

0개의 댓글