- 추상클래스(abstract class)와 인터페이스(interface)의 차이
1. 추상클래스(abstract class)란?
추상 메서드를 선언하여 상속을 통해서 자손 클래스에서 완성하도록 유도하는 클래스
→ 미완성 설계도라 표현하며, 상속을 위한 클래스이기 때문에 따로 객체를 생성할 수 없다.
abstract class 클래스이름 {
...
public abstract void 메서드이름();
}
2. 인터페이스(interface)란?
추상클래스가 미완성 설계도라면 인터페이스는 기본 설계도와 같음
→ 추상클래스처럼 다른 클래스를 작성하는데 도움을 주며, 다중상속(구현)이 가능하다.
interface 인터페이스이름 {
public static final 상수이름 = 값;
public abstract void 메서드이름();
}
3. 추상클래스와 인터페이스 차이
- 공통점
추상 메서드 : 메서드의 선언만 있고, 상속받은 클래스가 구현한다.
객체생성 불가 : new 키워드를 통해 객체를 생성할 수 없다.
- 차이점
추상클래스는 extends 키워드를 사용하여 상속하며, 다중 상속은 불가능
인터페이스는 implements 키워드를 사용하여 상속하며, 다중 상속이 가능
추상클래스는 일반 변수, 생성자, 일반 메서드, 추상 메서드를 모두 가질 수 있음
인터페이스는 상수와 추상 메서드만 가질 수 있고, 생성자와 일반 변수는 가질 수 없음
더보기
추상클래스(abstract class) : extends(상속, 확장의 느낌)
→ 자신의 기능들을 하위로 확장시키며, 상속할 각 객체들의 공통점을 찾아 추상화시켜놓은 것
→ 같은 부모 클래스를 상속하며, 부모 클래스가 가진 기능들을 구현해야 하는 경우
인터페이스(interface) : implements(상속, 구현의 느낌)
→ 인터페이스에 정의된 메서드를 각 클래스의 목적에 맞게 동일한 기능으로 구현하는 것
→ 다른 부모 클래스를 상속하더라도 같은 기능이 필요한 경우
추상클래스 : is "A" (~이다)
인터페이스 : has "A" (~을 할 수 있는)
4. Creature 예제를 통한 차이 비교
- Creature 추상클래스
public abstract class Creature {
// 생명체가 갖출 요소들
private int x; // x 좌표
private int y; // y 좌표
private int age; // 나이
public Creature(int x, int y, int age) {
this.age = age;
this.x = x;
this.y = y;
}
// 나이를 먹는 것과 x 좌표로 이동하는 것은 공통적인 기능이라 일반 메서드로 구현
public void age() {
age++;
}
public void move(int xDistance) {
x += xDistance;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
// 모든 생명체에 필요한 기능이지만 각각 생명체에 따라 다른 기능으로 구현을 해야하기에 추상메서드로 선언
public abstract void attack();
public abstract void printInfo();
@Override
public String toString() {
return "x : " + x + ", y : " + y + ", age : " + age;
}
}
- Animal 추상클래스
// 생명체이기에 Creature 추상클래스를 상속
public abstract class Animal extends Creature {
public Animal(int x, int y, int age) {
super(x, y, age);
}
@Override
public void attack() {
System.out.println("몸을 사용하여 공격!!");
}
// printInfo 메서드가 없는 이유?
// Animal 클래스 또한 추상클래스이기에 Animal 클래스가 상속할 클래스에 구현을 위임
}
- Human 추상클래스
// 생명체이기에 Creature 추상클래스를 상속
// Human은 말을 할 수 있기에 Talkable 인터페이스 구현
public abstract class Human extends Creature implements Talkable {
public Human(int x, int y, int age) {
super(x, y, age);
}
@Override
public void attack() {
System.out.println("도구를 사용!!");
}
@Override
public void talk() {
System.out.println("사람은 말을 할 수 있다.");
}
}
- Talkable 인터페이스
// Human에게 구현시킬 인터페이스
public interface Talkable {
abstract void talk();
}
- Pigeon 일반클래스
// 동물이라 Animal 추상클래스 상속
// 날 수 있는 동물이라 Flyable 인터페이스 구현
public class Pigeon extends Animal implements Flyable{
public Pigeon(int x, int y, int age) {
super(x, y, age);
}
@Override
public void fly(int yDistance) {
setY(getY() + yDistance);
}
@Override
public void flyMove(int xDistance, int yDistance) {
setY(getY() + yDistance);
setX(getX() + xDistance);
}
@Override
public void printInfo() { // 일반클래스이기에 printInfo도 구현
System.out.println("Pigeon -> " + toString());
}
}
- Flyable 인터페이스
// 새종류의 동물에게 구현시킬 인터페이스
public interface Flyable {
void fly(int yDistance);
void flyMove(int xDistance, int yDistance);
}
- Swimable 인터페이스
// 수영을 할 수 있는지에 대한 인터페이스
public interface Swimable {
void swimDown(int yDistance);
}
여기서 추상클래스와 인터페이스의 차이가 나타난다.
아래에 Kevin이라는 Human과 Turtle이라는 Animal을 만들건데, 두 생명체는 모두 수영을 할 수 있다. 근데 만약 Merry라는 Human을 만들었는데, Merry는 수영을 못한다면?
추상클래스 Creature나 Human에서 swimDown 메서드를 선언할 경우, Merry는 swimDown을 무조건 구현해야 한다.(추상클래스는 단일상속만 가능하기에 다른 클래스를 상속 받을 수도 없다.)
그러나, Swimable처럼 인터페이스로 선언한다면 다중상속이 가능하기에 선택적으로 구현시킬 수 있다.
- Turtle 일반클래스
// 동물이기에 Animal 추상클래스 상속
// 수영을 할 수 있기에 Swimable 인터페이스 구현
public class Turtle extends Animal implements Swimable{
public Turtle(int x, int y, int age) {
super(x, y, age);
}
@Override
public void swimDown(int yDistance) {
setY(getY() - yDistance);
}
@Override
public void printInfo() {
System.out.println("Turtle -> " + toString());
}
}
- Kevin 일반클래스
// Kevin은 사람이기에 Human 추상클래스 상속
// Kevin은 프로그래머이며, 수영도 할 수 있다. (다중 구현)
public class Kevin extends Human implements Programmer, Swimable{
public Kevin(int x, int y, int age) {
super(x, y, age);
}
@Override
public void coding() {
System.out.println("Hello World!");
}
@Override
public void swimDown(int yDistance) {
setY(getY() - yDistance);
if(getY() < -10) {
System.out.println("너무 깊이 들어가면 죽을수도 있어!!");
}
}
@Override
public void printInfo() {
System.out.println("Kevin -> " + toString());
}
}
- Programmer 인터페이스
public interface Programmer {
void coding();
}
- Main 일반클래스 (실행부)
public class Main {
public static void main(String[] args) {
Pigeon p = new Pigeon(5,10,14);
p.printInfo();
p.age();
p.move(100);
p.printInfo();
p.fly(5);
p.printInfo();
p.flyMove(10, 20);
p.printInfo();
p.attack();
System.out.println();
Kevin kev = new Kevin(0, 0, 35);
kev.printInfo();
kev.age();
kev.move(10);
kev.printInfo();
kev.attack();
kev.coding();
kev.swimDown(20);
kev.printInfo();
kev.talk();
System.out.println();
Turtle tur = new Turtle(100, -10, 95);
tur.printInfo();
tur.age();
tur.move(-100);
tur.printInfo();
tur.attack();
tur.swimDown(1000);
tur.printInfo();
}
}