Skills/Java

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

aoaa 2022. 8. 23. 22:34

 추상 클래스와 인터페이스는 비슷한 개념이지만 차이점이 있는데 자세한 차이점을 알아보겠습니다. 

 


1. 추상 클래스

 먼저 추상 클래스는 일반 클래스와 별 차이가 없지만, 추상 메서드를 선언하여 상속을 통해 자손 클래스에서 완성하도록 유도하는 클래스라고 정의할 수 있겠습니다. 클래스를 설계도라고 하면 추상 클래스는 미완성 설계도로 표현할 수 있으며, 이는 상속을 위한 클래스로 따로 객체를 생성할 수 없다는 특징을 가집니다. 

abstract class ClassName {
	...
    public abstract void Methodname();
}

 class 앞에 abstract 키워드를 붙여 상속을 통해 구현해야 한다는 것을 알려주고, 선언부만 작성하는 추상메서드를 선언할 수 있습니다.


2. 인터페이스

 인터페이스는 추상 클래스와 달리 미완성이아닌 기본 설계도라고 할 수 있으며, 추상 클래스와 같이 다른 클래스를 작성하는 데 도움을 주는 목적으로 작성합니다. 가장 큰 차이점은 다중상속이 가능하단 점이 있습니다. 또한 추상 클래스보다 추상화의 정도가 높아서 몸통을 갖춘 일반 메서드와 멤버 변수를 구성원으로 가질 수 없습니다. 이 때, 모든 멤버 변수는 public static final이어야 하는데 이는 생략할 수 있고, 모든 메서드도 public abstract이지만 마찬가지로 생략할 수 있습니다. 

 이는 인터페이스 변수가 아무 인스턴스도 존재하지 않는 시점이기 때문에 스스로 초기화 될 권한이 없기때문에 public static final을 사용해 구현 객체의 같은 상태를 보장하기 위함입니다. 

interface InterfaceName {
	public statid final variable = value;
    public abstracat void MethodName();
}

3. 상세한 차이점

 위에서 이론적인 차이점은 다중상속이 가능하다고 했습니다. 인터페이스가 다중 상속이 가능하다고 했는데 굳이 추상 클래스와 인터페이스를 나눈 이유가 무엇일까요..?

3.1 공통된 기능 사용 여부

 코드를 설계할 때, 모든 클래스를 인터페이스를 사용해 구성한다면, 공통적으로 필요한 기능들도 모든 클래스에서 오버라이딩(@Override)하여 재정의해야하는 번거로움이 생기게 됩니다. (implements)

 Java는 기본적으로 하나의 클래스만 상속이 가능하기 때문에 각각 다른 추상클래스를 상속하는데 공통된 기능이 필요하다고 하면, 해당 기능을 인터페이스로 작성하여 구현한다면 편할 것입니다. 예시를 들어서 살펴보겠습니다.

 

 먼저 객체지향에 있어 상속은 Super - Sub클래스 개념으로 상위(Super)로 갈수록 추상화 된 것이고, 하위(Sub)로 갈수록 구체화 되었다고 말할 수 있습니다. 이는 하위 클래스는 상위 클래스다라고 말할 수 있다는 것입니다. 

 문장을 예시로 든다면, '아버지는 할아버지이다', '엄마는 딸이다'라고 한다면 뭔가 적절치 않다는 느낌이 듭니다. 

위의 관계도를 통해 또 다른 예시를 든다면 '포유류는 동물이다' '고래는 포유류다' 라고 한다면 적절한 문장이라고 보여집니다. 이처럼 상속이라 함은 is kind of로 해석이 되는 관계를 뜻한다고 보면 됩니다. 포유류는 동물의 한 종류, 고래는 포유류의 한 종류라고 한다면 자연스러운 것을 확인할 수 있게 됩니다. 이를 코드를 통해 작성해보겠습니다. 

// 동물(Animal) 추상화 class
public abstract class Animal {
	private String gender;
    private int age;
    
    public Animal(String gender, int age){
    	this.gender = gender;
        this.age= age;
        }
        
        public abstract void attack();
}        


// 포유류(mammal) 추상화 class
public abstract class mammal extends Animal { 
	public Animal (String gender, int age) {
    super(gender, age);
    }
    
    @Override 
    public void attack() {
    	System.out.println("Attack!");
        }
}

 Animal 클래스를 보면 공격하는 attack() 메서드를 볼 수 있습니다. 이는 모든 동물에게 필요한 기능이지만 각 동물에 따라 다른 기능을 구현해야하기 때문에 추상메서드로 선언하여 하위 클래스에서 처리하도록 했습니다. 상위 클래스에서 선언한 추상메서드를 앞으로 동물 클래스를 상속할 클래스에게 위임한 것이 됩니다. 

 

 추상 클래스가 a kind of을 의미했다면 인터페이스는 is able to라고 해석할 수 있습니다. 인터페이스를 하나 작성 해보겠습니다.

// bird class (일반 클래스)
public class bird extends Animal implements Flyable {
	public bird(String gender, int age) {
    	super(gender, age);
	}

	@Override
    public void fly(int Distance) {
    set...
    {
    
    @Override
    public void flymove(int Distance) {
    set...
    }
}    
    
// Flyable(인터페이스)
public interface Flyable {
	void fly(int Distance);
    void flyMove(int Distance);
}

 인터페이스는 클래스가 무엇을 할 수 있다고 하는 기능을 강제로 구현하는 기능을 합니다. 동물 중에 날 수는 있는데 수영을 할 수 없거나 달리지 못하는 경우가 있다고 가정해본다면, 이를 인터페이스로 구현하여 따로 선언해 날 수 있는 클래스에 구현시킨다면 코드의 가독성이 좋아지고 유지보수에 용이하다는 장점을 얻을 수 있게됩니다.

 

 정리하자면 추상 클래스는 상속 관계를 타고 올라갔을 때, 같은 조상 클래스를 상속하는데 완벽히 기능까지 똑같은 기능이 필요한 경우에 사용하며, 인터페이스는 다른 조상 클래스를 상고하는 데 같은 기능이 필요할 경우에 인터페이스를 사용한다고 정리해볼 수 있겠습니다. 

 

 

 

참조

'Skills > Java' 카테고리의 다른 글

Java - JVM & Garbage Collector  (0) 2022.09.16
Java - static import  (0) 2022.08.29
Java - ConcurrentHashMap  (0) 2022.08.21
Java - Generic, 변성  (0) 2022.08.13
Java - 정적 바인딩, 동적 바인딩  (0) 2022.08.06