본문 바로가기
개발자 꿈나무의 하루/01_Boot Camp

(네이버클라우드 부트캠프) 28일차 - Java프로그래밍 기초(추상클래스, 인터페이스,캡슐화)

by kk_naks 2024. 7. 3.

1. 추상클래스

  1.1 추상클래스의 필요성

     - 비슷한 기능을 하는 두개의 클래스를 공통의 메서드로 관리하기 위한 클래스이다. 

- 두개의 정렬 메서드를 확인 해보자 
- 2개의 메서드는 기능은 같지만, sorter.run()과 sorter.start()의 메서드명과 매개변수가 다르다.
- 같은 기능을 하지만 경우에 따라 2개를 각각 호출해야한다. 
  static void display(BubbleSort sorter, int[] values) {
    sorter.run(values);
  }

  static void display(QuickSort sorter, int[] values) {
    sorter.start(values, 0, values.length - 1);
  }

 

  1.2 추상클래스의 개념

     - 그렇기 때문에 추상클래스를 통해 공통의 분모를 수행하는 추상클래스를 생성한다.

- 추상클래스를 직접적으로 사용하지는 않지만, 같은 메소드와 같은 매개변수로 넘겨 줄수 있다.
public abstract class Sorter {
  public void sort(int[] values) {};
}

public class QuickSort extends Sorter {

  @Override
  public void sort(int[] values) {
    start(values, 0, values.length - 1);
  }
  //후략//
}

public class BubbleSort extends Sorter {

  @Override
  public void sort(int[] values) {
    int size = values.length;
    for (int i = 0; i < size - 1; i++) {
      for (int j = 0; j < size - i - 1; j++) {
        if (values[j] > values[j + 1]) {
          //System.out.printf("%d <==> %d\n", values[j], values[j + 1]);
          int temp = values[j];
          values[j] = values[j + 1];
          values[j + 1] = temp;
        }
      }
    }
  }
}
- 여기에 다형성 개념을 대입하면 부모클래스의 변수명으로 자식클래스 타입을 할당할 수 있다. 
- 또한 사용자는 Soter sort = new Soter(); 처럼 직접적인 사용을 할 수 없다. 
Sorter sort = new BubbleSort();
display(sort, values); // OK!

Sorter sort2 = new QuickSort();
display(sor2, values); // OK!

 

  1.3 추상클래스의 한계

     - 추상클래스를 선언하였지만, 자식클래스에서 추상클래스의 메서드를 사용 안할 수도 있다. 

- 하지만 추상클래스의 메소드를 사용 안하는 경우도 있다. 
public class MergeSort extends Sorter {

  void merge(int arr[], int l, int m, int r)
  { // 생략//
  }
}

 

  1.4 추상메서드의 활용

     - 추상클래스를 사용 안하면, 상속을 받는 의미가 없다.

- 따라서 추상클래스의 메소드를 강제적을 사용하게 하는 방법이 필요하다.
- 추상클래스의 메소드를 강제적으로 사용하게 하는 것이 바로 추상메서드 이다. 
public abstract class Sorter {

  // 메서드를 추상 메서드로 선언하는 순간
  // => 모든 서브 클래스는 반드시 이 메서드를 구현해야 한다.
  // => 구현하지 않으면 추상 클래스가 될 수 밖에 없다.
  // => 서브 클래스에게 구현을 강제하는 효과가 있다.
  public abstract void sort(int[] values);
}

 

  1.5 인터페이스의 등장

     - 이처럼 추상클래스를 가지고 메소드사용을 강제하는데 제약이 있어, 인터페이스를 사용하게 된다. 

- 추상메서드만 있을 경우, 객체 사용규칙을 정의하는 인터페이스로 전환 가능하다.
- 추상클래스 안에 일반 메서드가 있다면, 인터페이스로 전환이 불가능하다. 
public interface Sorter {

  // 인터페이스는 호출 규칙을 정의하는 것이기 때문에
  // 모든 메서드는 기본이 public 이고, abstract 이다.
  // => 다음과 같이 메서드 선언에 public 과 abstract를 생략해도 된다.
  void sort(int[] values);
}

 

2. 캡슐화

  1.1 캡슐화의 필요성 

     - 클래스의 필드 값에 직접적인 접근을 하면  해당 필드값을 참조하는 결과값도 영향을 받는다

- 필드에 직접적인 접근 보다 set과 get 메서드들을 통해 접근하면, 
- 변경에 따른 추가적인 필드 변경 메서드를 추가할 수 있다.

 

  1.2 접근제어자 

- private : 클래스에 소속된 같은 멤버만 접근 가능
- (default) : 같은 패키지에 소속된 멤버만 접근 가능
- protected : 같은 패키지에 소속되거나 자손 클래스의 멤버만 접근 가능
- public : 모두 접근 가능

*자식 클래스에서 상속 받아 만든 변수가 아니면 부모클래스로 생성해도 protected 접근불가

 

  1.3 싱글톤 패턴

     - 클래스의 생성자의 접근을 제한하며 static 메서드를 통해 하나의 인스턴스만 생성

public class Car{
	//생성자를 접근제한
    private Car();
    
    //하나의 값(전역변수)만을 가지는 인스턴스 선언
    private static Car instance;
    
    //인스턴스의 고유성 여부를 확인
    public static Car getInstance(){
    	if(instance == null){
        	//private은 같은 class내에서 접근 가능
        	instance = new Car();
        }
    //고유한 인스턴스 생성
    return instance;
    }
}