HAZEL

[ CH03. 객체지향 핵심 ] 추상 클래스 ,템플릿 메서드, 메서드 패턴 , 인터페이스, 여러 인터페이스 구현 , 인터페이스 상속 본문

PROGRAMMING/Java

[ CH03. 객체지향 핵심 ] 추상 클래스 ,템플릿 메서드, 메서드 패턴 , 인터페이스, 여러 인터페이스 구현 , 인터페이스 상속

Rmsid01 2021. 4. 26. 13:24

CH03. 객체지향 핵심 

: 패스트 캠퍼스 강의를 공부하고 정리한 내용입니다.

 

01. 추상 클래스 ( abstract class ) 

1. 추상 클래스란 ?

: 구현 코드 없이 메서드의 선언만 있는 추상메서드를 포함한 클래스

: 상속만을 위한 클래스

-  메서드 선언 ( declaration ) : 반환 타입 , 메서드 이름, 매개변수로 구성

-  메서드 정의 ( definition ) : 메서드 구현 ( implementation ) 과 동일한 의미 구현부를 가짐. ({})

int add(int x, int y); // 선언

int add(int x, int y){ } // 구현부가 있음, 추상 메서드 아님

 

- abstract 예약어 사용

- 추상 클래스는 new 할 수 없음 ( 인스턴스 화 할 수 없음 ) 

 

2. 추상 클래스 구현하기

  • 메서드에 구현 코드가 없으면 abstract 로 선언
  • abstract로 선언된 메서드를 가진 클래스는 abstract로 선언
  • 모든 메서드가 구현 된 클래스라도 abstract로 선언되면 추상 클래스로 인스턴스화 할 수 없음
  • 추상 클래스의 추상 메서드는 하위 클래스가 상속 하여 구현
  • 추상 클래스 내의 추상 메서드 : 하위 클래스가 구현해야 하는 메서드
  • 추상 클래스 내의 구현 된 메서드 : 하위 클래스가 공통으로 사용하는 메서드 ( 필요에 따라 하위 클래스에서 재정의 함 )

** 비스듬하게 있는 글 : 추상 메서드 , 추상 클래스 

** 추상 메서드가 없더라도 abstract를 붙여서, 추상 클래스로 만들어 줄수 있다. 그러나 그렇게 되면 new 를 할 수는 없다. 

public abstract class Computer {

    public abstract void display(); // 여기서는 메서드를 구체적으로 명시하지 않고, 역할을 하위 클래스로 !
    public abstract void typing();

    public void turnOn(){
        System.out.println("전원을 켭니다.");
        }
   }

 

3. 템플릿 메서드

  • 추상 메서드나 구현 된 메서드를 활용하여 코드의 흐름(시나리오)를 정의하는 메서드
  • final로 선언하여 하위 클래스에서 재정의 할 수 없게 함 - 메서드는 변하면 안됨. 왜냐하면 중요한 시나리오를 가지고 있어서! 
  • 프레임워크에서 많이 사용되는 설계 패턴
  • 추상 클래스에서 어떤 메서드를 구현하고 어떤것은 안할 것인가 -> 공통으로 사용할 것은 구현하고, 아니면 추상메서드로 남겨두기.
  • 이미 구현한 것이도, 다시 재정의가 필요하다면 할 수 있다. 하지만 바꾸면 안되는 것들은 final 을 이용한다. 
  • 추상 클래스로 선언된 상위 클래스에서 템플릿 메서드를 활용하여 전체적인 흐름을 정의 하고 하위 클래스에서  다르게 구현되어야 하는 부분은 추상 메서드로 선언하여 하위 클래스에서 구현 하도록 함

4. final 예약어

  • final 변수 : 값이 변경될 수 없는 상수
  public static final double PI = 3.14;

 

  • final 메서드 : 하위 클래스에서 재정의 할 수 없는 메서드
  • final 클래스 : 상속할 수 없는 클래스

: final 변수로 선언한 경우에는, 초기화하지 않고, System.out.println(Define.GREETING);  로 바로 불러와서 쓰이거나 이니멀(?) 을 이용해서 쓰인다고함. 

 

02. 인터페이스 

1. 인터페이스란 ?

모든 메서드가 추상 메서드로 선언됨 - public abstract

: 모든 변수는 상수로 선언됨 - public static final 

interface 인터페이스 이름{

    public static final float pi = 3.14F;
    public void makeSomething();
}

 

2. 인터페이스 정의와 구현 ( implements : 구현한다 ) 

: 클래스가 상속이 되는 관계인데, 구현을 하는데 다 구현을 하면, 추상클래스가 아니지만, 일부만 구현을 하면 추상 클래스라고 한다.

모두 구현을 하면, 인스턴스화 할수있는 클래스가 된다.

- 인터페이스는 상속이 아니라 '구현한다'라고 표현함.

3. 인터페이스 구현과 형 변환

  • 인터페이스를 구현한 클래스는 인터페이스 형으로 선언한 변수로 형 변환 할 수 있음
Calc calc = new CompleteCalc();
  • 상속에서의 형 변환과 동일한 의미 - 타입 상속 ! 
  • 클래스 상속과 달리 구현 코드가 없으므로 여러 인터페이스를 구현할 수 있음 ( cf. extends) 즉, 여러 인터페이스를 implements 할 수 있다. 
  • 형 변환되는 경우 인터페이스에 선언된 메서드만을 사용가능함

4. 인터페이스가 하는 일

- 클래스나 프로그램이 제공하는 기능을 명시적으로 선언

- 클라이언트 코드와의 약속, 클래스나 프로그램이 제공하는 명세

- 클라이언트 프로그램은 인터페이스에 선언된 메서드 명세만 보고 이를 구현한 클래스를 사용할 수 있음. 

  즉, 어떤 객체가 하나의 인터페이스 타입이라는 것은 그 인터페이스가 제공하는 모든 메서드를 구현했다는 의미 .

  다시말하면, 구현 단에서 한것은 사용할 때 모를 수 있다. 단순히, interface 를 보고 사용한다. 

- 인터페이스를 구현한 다양한 객체를 사용함 - 다형성 

 

5. 인터페이스와 다형성

: 하나의 인터페이스를 여러 객체가 구현하게 되면, 클라이언트 프로그램은 인터페이스 메서드를 활용하여 여러 객체의 구현을 사용할 수 있음. 

 

*** 다형성의 특징으로 인해, DB에 회원 정보를 넣는 dao(data access object)를 여러 DB 제품이 지원될 수 있게 구현함. 대체할 수 있음. 

 

6. 인터페이스의 여러가지 요소

- 상수

: 모든 변수( public, static, final ) 는 상수로 변환됨 

 

- 추상 메서드

: 모든 선언된 메서드는 추상 메서드  public abstract 

 

- 디폴트 메서드 ( 자바 8이후 ) 

 : 앞에 default 가 붙어서 메서드를 구현할 수 있다. 위에서 정의된 것을 다시 재정의 할 수 있다. 

: 구현을 가지는 메서드, 인터페이스를 구현하는 클래스들에서 공통으로 사용할 수 있는 기본 메서드

: 인터페이스를 구현한 클래스의 인스턴스가 생성되어야 사용가능하다.

 

* default 키워드 사용 

public interface Calc {
	default void desciption(){
        System.out.println("정수의 사칙 연산을 제공합니다.");
    }
 }

* 구현하는 클래스에서 재정의

public class CompleteCalc extends Calculator {
    @Override
    public void desciption() {
        System.out.println("CompleteCalc overriding");
    }
}

 

- 정적 메서드 ( 자바 8이후 )

 : 인터페이스 생성과 상관없이 인터페이스 타입으로 사용할 수 있는 메서드 

public interface Calc {

	static  int total(int[] arr){

        int total = 0;
        for(int num : arr){
            total += num;
        }
        return total;

 

- private 메서드 ( 자바 9 이후 ) 

: 인터페이스 내에 구현하며, implements 에서 사용하는 것도 아니고, 재정의하는 것도 아니고, 단지 인터페이스 내부에서만 사용하기 위해서 쓰는 것이다.  

: default 메서드나 static 메서드에서 사용한다.

  public interface Calc {
    // 아래와 같은 private 메서드는 자바 9 버전 이후로 만 가능하다. 
    private void myMethod(){
        System.out.println("myMethod");
    }

    private static void myStaticMethod(){
        System.out.println("myStaticMethod");
    }

}

 

7. 여러 인터페이스 구현 

자바의 인터페이스는 구현 코드가 없으므로 하나의 클래스가 여러 인터페이스를 구현할 수 있다. 

public class Customer implements Buy , Sell{

    @Override
    public void buy() {
        System.out.println("Customer.buy");
    }

    @Override
    public void sell() {
        System.out.println("Customer.sell");
    }
  
  // 이렇게 되면, 모호해지기 때문에 sell , buy 중에 선택하거나 새로 재정의를 해야한다.
  
    @Override  // 새로 재정의하기 
    public void order(){
        System.out.println("customer order");
    }
  }

 

: 디폴트 메서드가 중복 되는 경우는 구현 하는 클래스에서 반드시 재정의 하여야 함

  • 스테틱 메서드는 인터페이스 이름으로 호출하기 때문에 상관없지만, 디폴트 메서드는 인스턴스 쪽에서 구현될때 문제가 됨  ( 중복이 될경우 ) 구현하는 클래스에서 재정의해야함. 

: 여러 인터페이스를 구현한 클래스는 인터페이스 타입으로 형 변환 되는 경우 해당 인터페이스에 선언된 메서드만 사용 가능 함

  단, 구현 코드 끼리의 다중 상속은 안된다 ! 

다이아몬드 프로블럼 : 자바의 자동상속이 안되는 이유 -> 다중 상속이 안되고, 단일 상속만 된다.

다중상속을 하면 다양한 기능을 가질 수 있다는 장점이 있지만, 조금 모호해지는 특성이 있다. 
자바는 안정적인것을 선호하기 때문에, 여러개의 상속을 한꺼번에 하는것을 제공하지 않는다.  

 

8. 인터페이스의 상속

: 인터페이스 사이에도 상속을 사용할 수 있음. extends 키워드를 사용하며, 인터페이스는 다중 상속이 가능하고 구현 코드의 상속이 아니므로 타입 상속이라고 한다.

public interface MyInterface extends X, Y{
    void myMethod();
}

 

9. 클래스 상속과 인터페이스 구현 함께 사용

< 실무에서는 이렇게 같이 구현하는 경우가 많음 >

public class BookShelf extends Shelf implements Queue{

    @Override
    public void enQueue(String title) {
        shelf.add(title);
    }

    @Override
    public String deQueue() {
        return shelf.remove(0);
    }

    @Override
    public int getSize() {
        return getCount();  // public int getCount()  로 이미 Shelf 에서 구현되어있음.
    }
}