언어/자바

JAVA - 추상클래스와 인터페이스

ballde 2021. 9. 3. 14:53
  추상메서드 일반메서드 멤버 변수
인터페이스 O O - 디폴트 메서드가 생김 X
추상메서드 O O O
  • 자바 8부터 디폴트 메서드가 생겨서 인터페이스에서 구현도 가능함 → 잘 쓰이지 않음
  • → 만약 추가 메서드를 인터페이스에서 추가한다면, 이를 implements 한 모든 클래스에서 강제적으로 추상 메서드를 구현해야 하고 안 하게 되면 애러남 → 이럴 때 디폴트 매서드를 사용

추상 클래스

  • 추상 클래스는 A, B, C 비슷한 필드와 메서드를 공통적으로 추출해서 만들어진 클래스
  • 객체 생성 X - 상속을 위한 클래스이기 때문에, 규격만 잡음

예시) 사람 - 팔다리 얼굴 등등 -> 공통적인 변수 - 걷는다. 먹는다. -> 공통적인 메서드

추상 클래스를 왜 사용할까..

  • 필드와 메서드 이름을 통일하여 유지보수성을 높이고 통일성을 유지시키려고
  • 실체 클래스 구현 시 - 구현만 집중해서 시간 절약, 규격에 맞추려고

인터페이스

  • 추상 메서드의 집합 (상수, 추상 메서드, 디폴트 메서드, 정적 메서드도 사용 가능
public interface 인터페이스명 {

//상수
타입 상수명 = 값;

//추상 메소드
타입 메소드명(매개변수, ... );

//디폴트 메소드
default 타입 메소드명(매개변수, ... ){
  //구현부
}

//정적 메소드
static 타입 메소드명(매개변수) {
  //구현부
}

 
}
  • 동일한 목적 하에 동일한 기능을 수행하게끔 강제하는 것이 바로 인터페이스의 역할이자 개념
  • 다형성을 극대화
  • 다중 상속 가능

나중에 함수형 인터페이스, solid에 관해서 정리해서 링크

 

추상 클래스와 인터페이스는 뭐가 다를까...

추상클래스는 IS - A

인터페이스는 HAS - A 

자바는 한개의 클래스만 상속이 가능해서 해당 클래스의 구분을 추상클래스의 상속을 통해 해결하고 

할 수 있는 기능들을 인터페이스로 구현

 

public abstract class Creature {

    private int age;
    private int weight;

    public Creature(int age, int weight) {
        this.age = age;
        this.weight = weight;
    }
    

    public abstract void eating();
    public abstract void speaking();
    public abstract void printInfo();
}

생명체는 먹기와 말하기가 있지만 다른 기능으로 구현 해야해서 추상메서드로 선언했습니다.

public interface Kickable {

    public void kick();

}
public abstract class Human extends Creature implements Kickable {

    public Human(int age, int weight) {
        super(age, weight);
    }

   @Override
    public void eating() {
        System.out.println("상추를 먹는다.");
    }

    @Override
    public void speaking() {
        System.out.println("안녕하세요");
    }

  	@Override
    public void kick() {

    }

}

사람은 생명체기 때문에 Creator클래스를 상속.

근데 printInfo도 추상메서드인데 human클래스에 없는 이유는 상위 클래스에서 선언한 추상메서드를 앞으로 동물 클래스를 상속할 클래스에게 위임했기 때문입니다. 

그리고 kickable을 implement해줬습니다. creator에 안해주고 따로 뺀 이유는 물고기는 생명체인데 발이 없어서 발차기를 못하기 때문에 따로 인터페이스를 만들어줘서 구현해줍니다. -> 이런경우 인터페이스를 따로 선언해서 발차기만 할 수 있는 클래스에 구현시켜주면 됨 -> 가독성과 유지보수성에 좋다. 

인터페이스는 다중구현이 가능하기 때문에 상황에 맞게 인터페이스들을 쓰면 된다. 

내부 클래스(inner class) - 정적 클래스

  • 클래스나 인터페이스 내부에 선언
  • 외부 클래스의 모든 멤버들에 접근 가능
  • 보통 class 안에 static을 붙인다.
    1. 외부 인스턴스에 대한 참조가 존재하기 때문에 가비지 컬렉션이 인스턴스 수거를 하지 못하여 메모리 누수가 생길 수 있다.
    ⇒ static으로 만들고 싶지 않으면 따로 클래스 만드는 게 좋음

장점

  • 외부 클래스의 멤버에 쉽게 접근
  • 코드의 캡슐화 증가, 관련 클래스를 논리적으로 묶어서 표현
  • 외부에서는 내부 클래스에 접근 불가능

class Outer { static class StaticInnerClass { } }