본문 바로가기

[Kotlin&Spring] 5기 내일배움캠프

[Kotlin&Spring] 5기 Abstract Class 와 Interface

Kiosk 프로그램에 대한 과제를 하던 중에 MenuItem 과 햄버거, 음료수, 디저트 등의 클래스를 만들어야 했다

나는  MenuItem 을 추상화해 구현하는 여러 분야 음식 메뉴를 만드려고 했다

그런데 추상클래스를 사용해야할지, 인터페이스를 사용해야할지 고민이 되었다

개념을 복습해보고자 찾아보게 되었다

 

추상 클래스(Abstract Class)
객체를 생성할수 있는 클래스들(실체)들의 공통적인 필드나 메소드를 추출해서 선언한 클래스이다
추상클래스를 상속해서 실체 클래스를 만들 수 있게 한다

그리고 클래스 간의 연관관계 구축에 초점을 맞춘다

추상클래스는 new 연산자로 객체를 생성할 수 없다는 특징이 있다
오직 상속할 수만 있고, 즉 extends 키워드 뒤에만 올 수 있다

클래스 선언 시 abstract 키워드로 선언할 수 있다
필드에 사용가능한 변수에는 제한이 없다(static final의 상수가 아니어도 된다)
또한 접근제어자에도 제한없이 모두 사용가능하다

public abstract class ClassName {...}


자식클래스들은 new 연산자로 객체 생성이 가능하고, 객체로 추상클래스의 메소드를 호출할 수 있다

추상클래스는 일반 메소드와 추상메소드 모두 선언할 수 있다
추상 클래스의 추상 메소드는 아래와 같이 선언한다.

abstract ReturnType methodeName(Parameter parameter, ... );

 

실행부 {} 가 없다는 것이 특징이다.

메소드 선언부(리턴타입, 메소드명, 매개변수)만 동일하고 실행 내용은 자식 클래스마다 달라야 할 때 선언한다
추상메소드는 자식 클래스의 공통 메소드임을 정의한다
자식클래스에서 반드시 재정의(오버라이딩)해서 실행 내용을 채워야 한다

추상클래스를 사용하는 이유는 다음과 같다

1. 상속 받을 클래스들이 공통으로 가지는 메소드와 필드가 많아 중복 멤버를 통합할 때 사용한다
2. 부모, 자식클래스 간의 명확한 계층 구조가 필요한 경우에 사용한다
3. public 외의 다른 접근자 사용이 필요한 경우 사용한다

인터페이스(Interface)는 사전적으로 두 장치를 연결하는 접속기를 말한다
인터페이스를 통해 객체 간의 연결을 해 다른 인터페이스 구현 객체를 사용할 수 있게 한다
다른 구현 객체가 추가/변경되었을 때 코드를 변경하거나 수정하는 작업이 필요하지 않아 다형성 구현에 좋다

인터페이스는 class 키워드가 아닌 interface 키워드로 선언한다

접근제한자는 대부분 public 을 사용하고 default 로도 선언 가능하다

public interface InterfaceName{...}


인터페이스가 가질 수 있는 멤버는 한정적이고 아래와 같다

 

1. public 상수 필드 

필드의 경우 항상 public static fianl 의 상수만 갖는다

따라서 생략해도 컴파일시 자동으로 생성된다

2. public 추상 메소드

추상메소드의 경우 기본적으로 public 접근제한자를 갖고,  따라서 더 낮은 접근 제한으로 재정의할 수 없다

3. public default 리턴타입 메소드(매개변수) 

public default 메소드의 경우 {} 내에 실행부가 있다

재정의시 default 키워드 제거해야 한다는 특징이 있다

4. public/private static 리턴타입 메소드(매개변수)

{}내에 실행부가 있고, 정적 메소드이기 때문에 인터페이스명으로 접근해 이용한다

5. private 메소드

디폴트 메소드 내에서만 호출이 가능하다

디폴트와 정적메서드의 중복 코드를 줄이기 위해 사용한다

6. private static 메소드

디폴트 메소드 또는 static 메소드 내에서도 호출이 가능하다

 

구현 객체 선언방법은 아래와 같다

public class ClassName implements InterfaceName {}

 

이 클래스는 인터페이스를 통해 사용할 수 있으며 인터페이스의 추상 메소드를 재정의했다는 뜻을 나타낸다

클래스는 여러개의 인터페이스를 구현할 수 있다
인터페이스 간의 상속이 가능하다

또한 인터페이스 간에 클래스와 달리 extends 키워드 뒤의 여러 인터페이스로 다중 상속이 가능하다
단, 모든 인터페이스의 추상메소드 재정의가 수반되어야한다

인터페이스와 구현 객체 간의 자동타입변환(upcasting)과 강제타입변환(downcasting)이 가능하다

인터페이스는 다음과 같은 이유로 사용한다

1. 서로 관련성 없는 클래스들을 형제관계로 묶고 싶을 때 사용한다
2. 다중 상속/구현을 통해 추상화 설계를 해야할 때 사용한다
3. 구현 객체가 같은 동작(메서드)을 한다는 것을 보장하기 위해 사용한다

마커 인터페이스(Marker Interface)
마커 인터페이스란 interface 키워드와 인터페이스명만 선언되어 있는 경우를 말한다
객체의 타입에 대한 정보 제공만 하는 경우로 타입체크가 필요할 경우 사용한다
예로 여러 전자기기가 있을 때 세탁기, 조리 도구의 2가지로 나누면 되는데 가스레인지, 냉장고, 버너, 세탁기, 전조기 등이 있는 경우 세탁도구, 조리도구를 구현하면 간단하게 표현할 수 있다

자바의 대표적인 마커 인터페이스는 Serializable(직렬화), Cloneable(깊은 복사)이 있다

 

결론적으로 나는 위의 MenuItem과 Burgers, Drinks, Deserts 의 구현을 추상클래스로 나타내었다

Burger, Drinks, Desert가 공통으로 가지는 메소드와 필드가 많아 중복 멤버와 중복 코드가 많아 통합하고자 했다
또한 형제 간의 대체 가능한 관계가 아닌 MenuItem과 Burger 등 간의 명확한 상속과 계층 구조가 필요했다

MenuItem

위 MenuItem 의 추상화 클래스를 아래 Burgers 클래스가 상속받음으로서 코드 작성 부분이 깔끔해졌다

Burgers 클래스

 

오늘도 하나 알아간다고 생각하면 앞으로 공부할 날들이 모여 뭐든지 이룰 수 있을 것이라고 생각한다

차근차근 열심히 힘내보자 ~