인터페이스와 추상클래스

이한수·2022년 1월 15일
0

JAVA

목록 보기
2/9
post-thumbnail

인터페이스와 추상클래스 둘 모두 설계도로써의 역할을 할 수 있으며 객체를 생성하지 못한다는 공통점이 있다.
물론 여기서 좀 더 자세히 얘기하자면 둘 다 상속받아 사용할 수 있다는 점과 상속관계를 이용하여 다형성을 활용할 수 있다는 점이다.

굳이 차이점을 꼽자면 크게 잡아서

1)인터페이스
-다중상속이 가능하다.
-implements 키워드를 이용한다.
-상수로만 이루어져 있다.

2)추상클래스
-다중상속이 불가능하다.
-extends 키워드를 이용한다.
-상수가 아닌 일반멤버변수 선언이 가능하다.

원래 인터페이스는 추상클래스와 구체화된 메소드를 가질 수 없다는 점이 있었다.

인터페이스는 Java8버전 부터 디폴트메소드 , 
정적메소드를 지원하여 구체화된 
메소드를 명시하고 사용할 수 있게 되었으며 
Java9버전 부터는 private 메소드를 구현하여 사용할 수 있다. 
단 ,상속받은 클래스에서 재정의하여 사용은 불가능하다.

참고 : 인터페이스에서 명시된 상수와 메소드들은
상수 구현 예약어와 추상메소드 예약어를 명시적으로 쓰지 않아도 컴파일 과정에서 자동으로 상수와 추상메소드로 변환된다.
ex)
상수의 경우 ,
int ERROR = -999; 라는 변수를 컴파일 시
public static final int ERROR 가 된다.
메소드의 경우,
int add(int num1 , int num2); 라는 메소드가 컴파일시
public abstract int(int num1,int num2); 로 바뀐다.

대략 이론적으로 이렇게 차이가 있구나 받아들이기는 쉬웠지만 워낙 비슷해서 굳이 이렇게 구분해놓은 이유가 해결이 안되었다. 그래서!!!!
어떻게 사용되는 방식에서 다른지 말해보려고 한다.

결론적으로 추상클래스는 IS-A 관계 ,
인터페이스는 HAS-A 관계를 표현하는데 적합하다.

그럼 이 이 관계의 차이점을 뭘까??

IS-A 관계 : 일반적인 개념과 구체적인 개념의 관계이다. 예를 들어 Human.classAnimal.class가 있다고 가정해보자 . 이때 사람은 사람이 될 수도 있고 동물이 될 수도 있다. 이러한 관계를 의미한다.

HAS -A 관계 : 예를 들자면 Student.classSubject.class 가 있다 가정해보자. 이때 학생의 정보는 과목의 정보를 가지고 있거나 과목이 학생의 정보를 가지고 있을 수는 있지만, 학생이 과목이다. 과목이 학생이다라고 보기에는 무리가 있다.
이처럼 한 클래스가 다른 클래스를 소유한 관계라고 볼 수 있다.

말로 설명하기 보다는 코드로 보자면,

public abstract class Animal{

private int age;

public Animal(){
	age = 1
}
public void oneYear(){
	age++;
}

public abstract void move();
public abstract void sound();
}

생명이 처음 태어나면 1살이 된다는것을 생성자와 age값을 이용하여 셋팅하였고 , 추상메소드는 동물별로 다르게 기능을 구현해야 하므로 추상메소드로 선언하였습니다.

public class Human extends Animal{

@Override
public void move(){
	System.out.println("두 발을 이용하여 걷는다");
}

@Override
public void sound(){
	System.out.println("언어를 이용하여 말한다.");
	}
}

public class Bird extends Animal{

@Override
public void move(){
	System.out.println("날개를 이용하여 이동합니다.");
}

@Override
public void sound(){
	System.out.println("짹짹 울음소리를 낸다.");
	}
}

이렇게 포괄적인 개념에서 구체적인 개념으로 뻗어나가는 과정에서 표현되는 방식에 적합하다.

그럼 여기서 인터페이스를 적용시키자면 어떻게 사용하는게 좋을까??

동물별로 그들만의 할 수있는 능력이 있을것이다 위에 Animal클래스를 구현받은 클래스들 중에 몇몇은 가능하고 몇몇은 불가능한것을 추상메소드에 구현하기에는 적합하지 않다.
이때 인터페이스는 다중상속이 가능하기 때문에 기능별로 구현을 해둔다음 이러한 기능이 필요한 클래스에서 부분적으로 상속받아 사용할 수 있다.

이렇게 추상클래스는 클래스끼리의 결합도가 높지만 인터페이스는 결합도가 떨어지는 대신 유연성을 제시한다.

아래에 예시로 든 클래스에서 Swimmable , Flyable ,Playball인터페이스를 이용할것이다.
Swimmable에는 swim메소드를 , Flyable에는 fly메소드를
Playball인터페이스를 play메소드를 추상메소드로 해놓았다.

public class Turtle extends Animal implements Swimmable{

@Override
public void move(){
	System.out.println("4개의 발을 이용합니다.");
}

@Override
public void sound(){
	System.out.println("거북거북(??)이라 말한다.");}     

@Override
    public void swim(){
    	System.out.println("헤엄을 칠 수 있다.");
    }

}


public class Bird extends Animal implements Flyable{

@Override
public void move(){
	System.out.println("날개를 이용하여 이동합니다.");
}

@Override
public void sound(){
	System.out.println("짹짹 울음소리를 낸다.");}     

@Override
    public void fly(){
    	System.out.println("날 수 있다");
    }
 
 }

public class Human extends Animal implements 	Swimable , Playball{

@Override
public void move(){
	System.out.println("두 발을 이용하여 걷는다");
}

@Override
public void sound(){
	System.out.println("언어를 이용하여 말한다.");
}

@Override
    public void swim(){
    	System.out.println("수영을 할 수 있	다.");
    }

@Override
public void play(){
	System.out.println("공을 가지고 논다.");
  	}

}

보면 각 구현 클래스별로 필요한 기능별로 필요한 인터페이스를 따로 설정하여 사용할 수 있다. 만일 각 클래스별로 다른 클래스를 상속받았는데 같은 기능이 필요한 경우라면 더욱 유용하다.
물론 추상클래스만큼 반복되는 코드의 수를 줄이기에는 무리가 있지만 ,
다중상속을 이용하여 각 기능들을 독립적으로 사용함으로써 유지보수 하기에도 편하고 변경에 유연하다.

고로, 최종적으로 다시 한번 정리하자면
둘 다 상속받은 클래스에서 공통적으로 사용될 메서드를 선언해놓는다는 점에서는 같으나 ,
단일상속만 가능하기 때문에 결합도가 높아 반복되는 코드를 그만큼 줄일수는 있지만 조상클래스가 바뀔경우 모든 하위클래스가 같이 변경되어야하는 IS-A관계를 표현하기에는 추상클래스.

다중상속이 가능하기 때문에 느슨하게 결합하여 추상클래스만큼 반복되는 코드를 줄이기는 힘들지만 , 유지보수 및 변경에 용이하여 HAS-A 관계를 표현하는데 적합한게 인터페이스
라고 볼 수 있다.

추가적으로 학습되어지는 부분이 있으면 나중에 더욱 추후에 추가해서 정리해야겠다!!

(잘못알고 있거나 정정 및 추가하고 싶은 내용이 있으시다면 댓글로 알려주시면 감사하겠습니다!!)

profile
성실하게

0개의 댓글