[Java] 객체지향 프로그래밍(oop) - 제어자(modifiers)

SolChan Kim·2023년 12월 12일

📖제어자(modifier)란?

  • 클래스, 변수, 메서드의 선언부에 사용되어 부가적인 의미를 부여한다.

  • 제어자는 크게 접근 제어자그 외에 제어자로 나뉜다.

==접근 제어자==
public, protected, default, private

==그 외 제어자==
static, final, abstract, native, transient, synchronized,
volatile, strictfp
  • 하나의 대상의 여러 개의 제어자를 조합해서 사용할 수 있으나,
    접근제어자는 단 하나만 사용할 수 있다.

📖static : 클래스의, 공통적인

public class Static {
	// 클래스 변수 : 인스턴스 생성없이 사용 가능
	static int x = 100, y = 200;
	
	// 클래스 초기화 블럭 : static변수의 복잡한 초기화 수행
	public Static() {}
	
	// static메서드 : 인스턴스 생성없이 호출 가능
	static int add(int x, int y) {
		return x + y;
	}
	
	public static void main(String[] args) {
		System.out.println(Static.add(x, y));
	}
}

📖final – 마지막의, 변경될 수 없는

  • 대표적인 final클래스 : String, Math클래스

// 클래스앞에 final이 붙으면 다른 클래스의 조상이 될 수 없다.
final class Final {
	// 변수 앞에 final이 붙으면 상수
	final int X = 100;
	
	// final로 지정된 메서드는 오버라이딩 불가
	final int getX() {
		return X;
	}
}

📖생성자를 이용한 final멤버변수 초기화

  • final이 붙은 변수(상수)는 보통 선언과 초기화를 동시에 진행하지만
    인스턴스 변수의 경우 생성자에서 초기화 할 수 있다.
public class Card {
	final int WIDTH, HEIGHT;
		
	// 생성자에서 매개변수를 받아 상수 초기화 진행
	public Card(int w, int h) {
		WIDTH = w;
		HEIGHT = h; 
	}
}

public class CardTest {
	public static void main(String[] args) {
		Card card = new Card(50, 50);
		// card.WIDTH = 60; Error : 상수는 값 변경 불가
	}
}

🤔상수를 생성자에서 초기화하면 뭐가 좋을까?

  • 상수를 선언함과 동시에 초기화를 진행한다면
    해당 클래스에 모든 인스턴스는 동일한 상수값을 가지게 된다.

    • 모든Card인스턴스는 동일한 WIDTH, HEIGHT값을 가지게 된다.
  • 해당 클래스에서 다른 상수 값을 가지고 있는 인스턴스를
    만들고 싶을 경우 상수를 생성자에서 초기화 해야한다.

    • 서로다른 WIDTH, HEIGHT값을 가진 Card인스턴스를 만들고 싶을 경우

📖abstract

  • 추상의, 미완성의라는 의미에 제어자

  • abstract가 사용될 수 있는 곳 : 클래스, 메서드

    • 클래스 : 클래스 내에 추상메서드가 선언되어 있음을 의미함
    • 메서드 : 선언부만 작성하고 구현부는 작성하지 않는 추상메서드를 의미
abstract class AbstractTest{ // 추상클래스
	abstract void abstractMethod(); // 추상메서드
}
  • 추상메서드가 정의된 클래스 역시 미완성 클래스이기 때문에
    클래스 앞에 abstract를 붙여서 이 클래스가 추상메서드를
    포함하고 있고, 인스턴스를 생성할 수 없다라는 것을 알려줘야한다.
    • 상속을 통해서 자손클래스에서 완성되어야 인스턴스 생성 가능

📖접근 제어자

  • 멤버 or 클래스에 사용되어 외부로부터 접근을 제한한다.

  • 접근 제어자가 사용될 수 있는 곳 : 클래스, 멤버변수, 메서드, 생성자

  • 클래스에는 public과 default만 사용할 수 있다.

  • 멤버변수와 메서드에는 접근제어자 4개를 모두 사용할 수 있다.

    • default를 실제로 사용하지는 않는다.
      • 접근 제어자를 사용하지 않을 경우 default접근제어자를 사용한 것

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

캡슐화(Encapsulation)란?

  • 관련있는 변수와 함수(메서드)를 하나의 클래스로 묶고,
    외부에서의 직접적인 접근을 막는 것

캡슐화의 장점 : 정보은닉(Information Hiding)

  • 외부에서 객체접근하는데 있어서 정보를 숨기고,
    객체의 연산(메서드...)을 통해서만 접근이 가능하게 하는 것

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

  • 접근제어자를 이용해서 멤버변수는 private으로 해서 내부에 감춘다.

  • 메서드는 public으로 해서 외부에 노출시킴으로 같은 클래스에 정의된
    멤버들끼리는 서로 자유롭게 접근하고 외부에서는 메서드를 통해서만
    멤버변수에 접근할 수 있는 구조로 만든다.

  • 외부에서는 객체의 노출된 public 메서드만 호출이 가능하고
    실제 내부가 어떻게 되어 있는지 알 수 없다.

public class Time {
	private int hour, minute, second;
	
    // 해당 멤버변수들은 외부클래스에서 직접접근 불가 
	public Time(int h, int m, int s) {
		setTime(h, m, s);
	}
	
	public void setTime(int h, int m, int s) {
		if(s >= 60 ) {
			m++;
			s -= 60;
		}
		
		if(m >= 60) {
			h++;
			m -= 60;
		}
		
		if(h >= 24) {hour = 0;}
		
		this.hour = h;
		this.minute = m;
		this.second = s;
	}
	
	public void setMinute(int m) {
		minute += m;
		
		if(minute >= 60) {
			hour++;
			minute -= 60;
			if(hour >= 24) {
				hour = 0;
			}
		}
	}
	
	public void getTime() {
		System.out.println(hour + " : " + minute + " : " + second);
	}
	
}

public class TimeTest {
	public static void main(String[] args) {
		Time t1 = new Time(23, 59, 59);
		// t1.hour = 546546; Error : private로 외부에 접근을 제한하고 있다.
		t1.setMinute(40);
		
		t1.getTime();	
	}
}

📖생성자의 접근 제어자

  • 일반적으로 생성자의 접근 제어자는 클래스의 접근 제어자와 동일하다.

  • 필요에 따라서 생성자의 접근 제어자를 사용하여
    인스턴스의 생성을 제한할 수 있다.

  • 생성자의 접근제어자가 private인 경우 다른 클래스의 조상이 될 수 없다.

    • 자손클래스의 인스턴스를 생성하면 조상의 생성자를 호출하는데
      조상의 생성자가 private이라서 호출할 수 없기 때문

    • 클래스 앞에 final을 사용하여 상속을 통해 확장할 수 없는
      클래스라는 것을 알려주는 것이 좋다.

final class Singleton {
	// 내부적으로 인스턴스를 생성해서 접근제어자를 private로 감춘다.
	private static Singleton s = new Singleton();
	
	// 생성자의 접근제어자를 private로 지정할 경우
	// 연산자 new를 통해 인스턴스를 생성할 수 없다. 
	private Singleton() {}
	
	// 메서드에 접근제어자를 public을 사용함으로써 생성된 인스턴스에 접근한다.
	// 외부에서 인스턴스를 생성할 수 없기 때문에 static메서드로 정의
	public static Singleton getInstance() {
		// 참조변수s가 아무것도 참조하고 있지 않다면 인스턴스를 생성하여 s가 참조
		if(s == null) {
			s = new Singleton();
		}
		// 참조변수 s를 return한다.
		return s;
	}
}

public class SingletonTest {
	public static void main(String[] args) {
    	// 생성자의 접근제어자가 private라서
        // new 를 통한 인스턴스 생성 불가
		// Singleton s = new Singleton(); 
        
        // static메서드를 통해 이미 생성된 인스턴스를 참조한다.
		Singleton s1 = Singleton.getInstance();
	}
}

📖제어자 정리

0개의 댓글