본문 바로가기
[ Developer ]/Core Java

Java 8 인터페이스 vs 추상클래스

by 김현섭. 2016. 11. 8.
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

인터페이스 vs 추상 클래스 

예전에 이 캐캐묵은 논쟁에 대한 글을 쓴적이 있었는데 , 그 중 일부를 발췌해보면 

" 먼저 왜 자바는 인터페이스를 만들게 됬나를 생각해야 하며 , 다중상속은 이 둘을 구분하는데 중요한 맥이 아닙니다중요한것은 인터페이스가 추구하는 바를 추상클래스로 이루려면 지켜야 할 제약이 생기고 위험/복잡성 또한 생기기 마련입니다. 또한 약속된 관례가 없기 때문에 커뮤니케이에 문제가 생기며 의도가 불분명해 집니다.  그래서 행위의 틀  immutable 한 속성만으로 제한해서 유연성과 사용성을 극대화한것이 자바의 "interface" 입니다.  ... 후략 "

뭐 이런건데 이런 저의 글과 여러 무수한 논쟁들이 자바8의 등장과 더불어 소각장으로 직행해야 할 가비지가 되었습니다.

자바의 인터페이스가 자바8에서 엄청난 변화를 가져 왔는데요. 즉 디폴트 메소드 구현, 정적메소드 구현 등 인터페이스 자체도 심플한 "틀" 뿐 만 아니라 "구현" 을 가질 수 있게 되었습니다. 장점은 강력해 졌다겠는데 단점은 복잡한게 좋은거냐? C++ 에 비해 자바 인터페이스의 간결했던 그 장점을 던저벼리냐? 뭐 이렇게 말 하곤 합니다. 


에피소드 

자바 전문가인 내 친구 제임스는 이렇게 말했어 " 내 생각에 자바 8의 가장 중요한 변경은 람다가 아니야. 인터페이스가 정적, 디폴트 메소드를 가질 수 있게 되었다는 거지"  계속해서 말하길 " 인터페이스에 디폴트 메소드를 추가 할 수 있게 되었다는 것은 어쩔 수 없이 추상클래스를 써야했던 속박에서 나를 풀어 주었거든" 

이 말을 듣고 , 나도 굉장히 동감이 가더라구. 원래 자바 세계에서 추상클래스 VS 인터페이스에 대한 케케묵은 주제는 예전 부터 개발자들 사이에서 꽤 큰 논쟁거리였었는데 이 새로운 JDK 8 로 개발하는 새내기 개발자들에겐 이 두 개념을 구분하는 일이 더 어려워 질 거 같아. (역주 : 단순히 다중상속 되냐 안되냐가 아니란거죠) 

JavaWorld's Abstract classes vs. interfaces , StackOverflow's When do I have to use interfaces instead of abstract classes? Difference Between Interface and Abstract Class , and 10 Abstract Class and Interface Interview Questions Answers in Java .

위에 링크한 이런 것 들이 예전에는 꽤나 유용한 정보였지만 이제 유통기한이 지나버렸지. 자바8로 개발하기 시작하는 새내기들이 저런 글을 보면 더더욱 혼란에 빠질 것이 자명해보여.

자바8 에서 인터페이스와 추상클래스 사이에 존재하는 차이점에 관해 살펴보기 위해 먼저 해야할 것은 표준 문서를 살펴보는 것 인데 먼저 내용이 업데이트된 자바 튜토리얼 Abstract Methods and Classes  여기에 가보면 차이점과 유사점에 대해 설명은 해  놓았어.

차이점은 주로 데이타 멤버와 메소드들에 대한 접근성에 관한 것 인데 

추상클래스는 non-static 과 non-final 필드 및 public, private, protected 메소드를 사용 할 수 있다.
인터페이스는 public, static, final 을 상속할 수 있고 모든 상속 가능한 메소드는 public 이다. 

(하마 :  인터페이스를  "구현" 이 가능하게 바꾸었지만 아직 적절한(?) 한계를 두었다. 라는 건데, 일단 문법적 복잡도가 올라가 버렸습니다. 스칼라에는 인터페이스 키워드가 아예 없고, 자바8의 인터페이스와 비슷한 trait 이라는게 있는데  변화된 자바8의 인터페이스가 스칼라 영향을 받은게 아닌가 싶기도 합니다. 옛날부터 개발자들 사이에서 필요성이 언급되었던 부분에 대해 스칼라는 언어가 생겨났을때부터 적용을 한것이고 자바는 이제서야 적용을 한 것 이기도 하겠지요.)

문서에 보면 언제 추상클래스를 사용해야하고, 언제 인터페이스를 고려해야하나 에 대한 말이 있는데. 뭐 놀랍지도 않게도 위에 한 얘기를 뻔하게 되풀이 하고 있지. non-static 과 non-final 필드 및 public, private, protected 메소드가 필요하면 추상 클래스 쓰고 구체적인 구현이 없는 것 에 촛점을 맞추고 다중상속이 필요한 부분은 인터페이스쪽이 낫고... 뭐 이런..-.-;;  


자바는 알다시피 하나의 클래스에서 만 상속받을 수 있고, 여러개의 인터페이스로부터 구현 상속 될 수 있는데 인터페이스는 그래서 여러 타입(기능)들을 연관시켜서 구현 될 필요가 있는 상황에서 특별히 이득을 볼 수 있어. 고맙게도 자바 8 부터는 디폴트 메소드가 그런 일반적인 상황에서의 행동에 대한 지침을 미리 구현하여 제공 해 줄 수 있게 되었지. 
하마 : 예를들어 자동자인터페이스는 전진/후진/클락숀에 대한 틀만 제공하고 자동자 인터페이스를 구현상속한 우리는 클래스에 전진/후진/클락숀에 대한 실제 구현을 넣게 됩니다. 근데 세상은 빠르게 변화하고 자동차의 기본적인 틀 자체가 변화 하고 있습니다. 또한 상위에서 틀만 제공하면 하위에서 우리들은 구현을 도맞아야 하는데요.  예를들어 네비게이션이 자동차 틀의 기본이 되었다고 합시다. 그럼 하위에서 우리의 자동차에 네비게이션을 구현 상속해야하는데 네비게이션은 우리가 더 잘 알까요? 네비게이션 회사가 더 잘 알까요? 즉 상위에서 여러가지 틀들이 기본적으로 구현이 되어 있으면 가져다 쓰기 편리한거죠. 이런 이유로 자바8에서 인터페이스는 기본 구현을 가지게 되었습니다 )  


여기서 본능적인 질문하나 들어가는데....만약 두개의 인터페이스을 가지고 구현을 한 클래스가 동일한 시그니쳐를 가진 디폴트 메소드 두개를 상속 받았을 경우 어떻게 핸들링 할 수 있을까?  

NetBeans 8 에서는 에러를 내보내.



스냅샷을 보면 알 수 있듯이 컴파일러 에러가 나와. ( 클래스/디폴트 메소드/두개의 인터페이스 등 관련 정보와 함께) 이에 대해 내 친구 피터 버하스는 좀 더 상세한 글을 작성 했는데 다음 링크를 참고해봐 ( 자바 8 디폴트 메소드 : 무엇을 할 수 있고 무엇을 못하나? ) 동일한 시그니처를 가진 디폴트 메소드로 구현된 여러 개의 인터페이스를 상속받는데 관련된 몇가지 케이스를 살펴 볼 수 있지.


결론 

자바8은 기존 인터페이스에 비해 많은 기능을 제공했던 추상클래스들의 장점을 인터페이스에게도 베풀었다. 
이것이 암시하는 바는 현재 쓰여져 있는 많은 수의 추상 클래스들을 쉽게 대체 할 수 있게 되었다는것과 앞으로 추상클래스를 사용하여 작업 했어야할 많은 곳에서  디폴트 메소드를 가진 인터페이스로 대체 될 것이란 것이다.



부록 : 공식 문서에서 발췌) 

추상클래스와 인터페이스 언제 사용하나?

  • 추상클래스 
    • 여러개의 가까운 클래스들 사이에 동일한 코드를 나누어서 사용하고 싶을때.
    • 추상클래스를 상속한 클래스들이 많은 공통 메소드들과 필드와 public 보다 다양한 접근 제어자에 의해 사용하고 싶을때.
    • non-static 과 non-final 필드를 선언하고 싶을때.  결과적으로 객체들의 상태를 메소드에서 접근하고 수정 할 수 있게 되겠지.
  • 인터페이스
    • 크게 상관없는 클래스들이 너의 인터페이스를 구현해야 할 필요가 있을때. 예를들어 Comparable and Cloneable
    • 특정 데이터타입의 행위를 특별하게 구현하길 원할때 그러나 누가 그것의 행위를 구현 했는지에 대한 관심은 없을때 
    • 다중 구현상속의 이점을 누려야 할때 



출처 : 




'[ Developer ] > Core Java' 카테고리의 다른 글

[Java] 자바 자료형 (Data Type)  (0) 2016.11.18
[Java] 자바 변수 (Variable)  (0) 2016.11.16
[Java] 자바 연산자  (0) 2016.09.06
[Java] 자바 주석처리  (0) 2016.09.05
[Java] 자바 자료형 (Data Type)  (0) 2016.09.02