추상 클래스와 인터페이스
abstract class 와 interface class 는 둘 다 유사 개념에 대해 공통 코드를 만들 수 있고, 인스턴스를 바로 만들 수 없는 설계도 라는 공통점을 갖고 있다. 그렇다면 어떤 차이점을 갖고 있을까?
추상 클래스
abstract class (추상 클래스) 는 상속 (extends) 을 통해 구현될 수 있는 클래스 이다. 상속은 단일 상속 만 가능하다.
추상클래스는 IS-A 관계로 '무엇' 을 의미한다. 즉 무엇인가 가 어떤 특성(멤버 변수) 과 행동(메서드) 을 가지는 것을 정의할 수 있다. 따라서 멤버변수와 메서드를 구현할 수 있다.
추상 클래스의 확장
따라서 추상 클래스의 확장은, 특성이나 행동이 확장되는 것을 의미한다.
abstract class Animal {
abstract void eat();
void breathe() {
System.out.println("Breathing");
}
}
abstract class Bird extends Animal {
void fly() {
System.out.println("Flying");
}
}
이 경우 Animal 에서 Bird 로 확장되면서, fly 라는 행동이 추가되었다.
그리고 다수의 interface 와 abtract class 의 상속이 가능하다.
package my_package;
abstract public class OtherAbstractC extends MyAbstractC implements MyInterface, OtherInterface {
}
인터페이스
inteface (인터페이스) 는 이름에서 처럼, 클래스는 아니다. implements 를 통해 구현 될 수 있고, 다중 상속 이 가능하다.
인터페이스는 추상 클래스보다 더 추상화 된 것으로, 상수와 메서드 선언부 만 가질 수 있다.
추상클래스는 HAS-A 관계로 '할 수 있는' 을 의미한다. 따라서 인터페이스의 이름은 ~able 로 끝난다. (ex. Runnable)
인터페이스의 확장
interface Readable {
void read();
}
interface Writable extends Readable {
void write();
}
interface Editable extends Writable {
void edit();
}
class Document implements Editable {
@Override
public void read() {
System.out.println("Reading the document.");
}
@Override
public void write() {
System.out.println("Writing to the document.");
}
@Override
public void edit() {
System.out.println("Editing the document.");
}
}
public class InterfaceExample {
public static void main(String[] args) {
Document doc = new Document();
doc.read(); // "Reading the document."
doc.write(); // "Writing to the document."
doc.edit(); // "Editing the document."
}
}
읽을 수 있으면(Readable) 쓸 수 있고(Writable), 쓸 수 있으면 편집 할 수(Editable) 있다. 즉 확장될 수록 할 수 있는 것 이 많아진다.
Document 는 Editable 을 implements 하고 있으므로, 읽고 쓰고 편집할 수 있다.
HAS-A, IS-A 의 관계
IS-A, HAS-A 가 헷갈려서 찾아봤다.
그림처럼, IS-A 는 '무엇, 어떤 것' 을 나타낸다. 즉 자동차는 탈 것 이다.
HAS-A 는 '~를 할 수 있는' 을 나타낸다. 그런데 그림에서는 약간 헷갈릴 수 있다. 자동차는 엔진을 할 수 있는... 이 무슨 뜻이지... 라고 생각할 수 있다. 여기서는 차는 엔진을 가동할 수 있는 을 의미한다.
각각의 용도
- 추상클래스 는 implements 라는 키워드 처럼, 정의된 함수를 목적에 맞게 구현 하는 것을 말한다.
- 인터페이스 는 extends 라는 키워드 처럼, 자신의 기능들을 확장 시키는 것을 말한다.
(출처는 여기)
예시로 알아보는 추상클래스와 인터페이스
추상클래스는 어떤 것을, 인터페이스는 어떤 능력을 의미한다.
FE 개발자로 예시를 알아보자. (Abstract class 와 Interface 에 대한 글인데 FE 개발자인 이유는... 제가 FE 개발자 이기 때문입니다아.. 😌 그리고 아래 예시는 예시가 그렇다... 는거지 꼭 저렇지많은 않습니다 😌...)
FE 개발자는 개발자이다. FE 개발자는 HTML과 SCSS, TypeScript 를 다룰 줄 알아야 한다. SCSS 는 CSS 를 알아야 하고, TypeScript 는 JavaScript 를 알아야 한다.
FE 개발자이며 React 를 다룰 줄 알면 React 개발자가, Angular 를 다룰 줄 알면 Angular 개발자가, Vue 를 다룰 줄 알면 Vue 개발자가 된다. Jerry, James, Jenny 는 각각 React, Angular, Vue 개발자 이다.
이를 도식으로 그려보면 이렇다.
예시 코드
package fe_developer;
interface JavaScriptUsable {
void writeJavaScriptCode();
}
interface TypeScriptUsable extends JavaScriptUsable {
void writeTypeScriptCode();
}
interface CSSUsable {
void writeCSSCode();
}
interface SCSSUsable extends CSSUsable {
void writeSCSSCode();
}
interface HTMLUsable {
void writeHTMLCode();
}
interface ReactUsable {
void writeReactCode();
}
interface AngularUsable {
void writeAngularCode();
}
interface VueUsable {
void writeVueCode();
}
abstract class Developer {
abstract void writeHelloWorld();
}
class FEDeveloper extends Developer implements TypeScriptUsable, SCSSUsable, HTMLUsable {
@Override
public void writeJavaScriptCode() {
System.out.println("Write Clean JavaScript Code");
}
@Override
public void writeTypeScriptCode() {
System.out.println("Write Clean TypeScript Code");
}
@Override
public void writeCSSCode() {
System.out.println("Write Clean CSS Code");
}
@Override
public void writeSCSSCode() {
System.out.println("Write Clean SCSS Code");
}
@Override
public void writeHTMLCode() {
System.out.println("Write Clean HTML Code");
}
@Override
void writeHelloWorld() {
System.out.println("HelloWorld");
}
}
class ReactDeveloper extends FEDeveloper implements ReactUsable {
@Override
public void writeReactCode() {
System.out.println("Write Clean React Code");
}
};
class AngularDeveloper extends FEDeveloper implements AngularUsable {
@Override
public void writeAngularCode() {
System.out.println("Write Clean Angular Code");
}
}
class VueDeveloper extends FEDeveloper implements VueUsable {
@Override
public void writeVueCode() {
System.out.println("Write Clean Vue Code");
}
}
public class Main {
public static void main(String[] args) {
ReactDeveloper james = new ReactDeveloper();
james.writeHelloWorld();
james.writeTypeScriptCode();
james.writeReactCode();
AngularDeveloper jerry = new AngularDeveloper();
jerry.writeHelloWorld();
jerry.writeSCSSCode();
jerry.writeCSSCode();
jerry.writeAngularCode();
VueDeveloper jenny = new VueDeveloper();
jenny.writeHelloWorld();
jenny.writeHTMLCode();
jenny.writeVueCode();
}
}
출력 결과
// James
HelloWorld
Write Clean TypeScript Code
Write Clean React Code
// Jerry
HelloWorld
Write Clean SCSS Code
Write Clean CSS Code
Write Clean Angular Code
// Jenny
HelloWorld
Write Clean HTML Code
Write Clean Vue Code
'자바 Java' 카테고리의 다른 글
Collection 과 Map (왜 Map 은 Collection 을 extends 하지 않을까?) (3) | 2023.10.05 |
---|---|
Java 의 접근 제어자 - public, protected, default, private 에 대해서 (0) | 2023.09.23 |
왜 자바 애플릿은 지원이 종료되었을까 (0) | 2023.09.22 |
Java 의 역사와 특징 (0) | 2023.09.22 |
[자바의정석] 배열 (0) | 2023.02.12 |