인터페이스 특징
- 내부의 모든 메서드는 public abstract 로 정의 (default 메소드 제외)
- 내부의 모든 필드는 public static final로 정의 (상수)
- 클래스에 다중 구현 (implements) 지원
- 인터페이스 끼리는 다중 상속 (extends) 지원
- 인터페이스에도 static, default, private 제어자를 붙여 클래스 같이 구체적인 메서드를 가질 수 있음. 따라서 하위 멤버의 중복 메서드 통합을 어느정도 할 수 있겠지만 필드는 상수이기 때문에 중복 필드 통합은 불가능
- 인터페이스는 부모 자식 관계인 상속에 얽매이지 않고, 공통 기능이 필요할 때마다 추상 메서드를 정의해놓고 구현(implements)하는 식으로 추상클래스보다 자유롭게 붙였다 떼었다 사용
- 인터페이스는 클래스와 별도로 구현 객체가 같은 동작을 한다는 것을 보장하기 위해 사용하는 것에 초점
- 다중 구현이 된다는 점을 이용해, 내부 멤버가 없는 빈 껍데기 인터페이스를 선언하며 마커 인터페이스 로서 이용가능
- 보통 xxxable(~을 할 수 있는) 이런 형식으로 인터페이스 네이밍 규칙을 따름
추상 클래스 특징
- 추상클래스는 하위 클래스들의 공통점을 모아 추상화하여 만든 클래스
- 추상클래스는 다중 상속이 불가능하여 단일 상속만 허용
- 추상클래스는 추상 메소드 외에 일반클래스와 같이 일반적인 필드, 메서드, 생성자를 가질수 있음
- 이러한 특징으로, 추상클래스는 추상화(추상 메서드)를 하면서 중복되는 클래스 멤버들을 통합 및 확장을 할 수 있음
- 같은 추상화인 인터페이스와 다른점은, 추상클래스는 클래스들간의 연관 관계를 구축 하는 것에 초점을 둠
인터페이스 VS 추상클래스 사용
인터페이스나 추상클래스나 둘다 똑같이 추상 메소드를 통해 상속/구현을 통한 메소드 강제 구현 규칙을 가지는 추상화 클래스입니다.
하지만 이둘은 각각 고유의 몇몇 특징들을 가지고 있는데, 이러한 특징으로 인해 각각 사용처가 갈리게 됩니다. 또한 기능적인 부분 뿐만 아니라 인터페이스와 추상클래스가 내포하고 있는 논리적인 의미로서도 사용처가 나뉩니다.
예를들어 이둘은 대표적으로 '다중 상속' 기능 여부의 차이가 있지만, 이것이 포인트가 아니라 이에 따른 사용 목적이 다르다는것에 포인트를 맞춰야 합니다.
- 인터페이스 : implements 라는 키워드처럼 인터페이스에 정의된 메서드를 각 클래스의 목적에 맞게 기능을 구현하는 느낌
- 추상 클래스 : extends 라는 키워드를 사용해서 자신의 기능들을 하위 클래스로 확장 시키는 느낌
인터페이스 추상클래스 사용 예시
위와 같은 관계를 갖는 예제를 만들어 보겠습니다.
인간과 동물은 생명체를 상속하고, 각 생명체들은 구분에 따라 인간과 동물을 상속합니다.
그리고 각각 할 수 있는 기능들을 인터페이스로 구현합니다.
1. Creature(생명체) 추상클래스
기본적으로 생명체가 갖는 요소의 집합
public abstract class Creature {
private int x;
private int y;
private int age;
public Creature(int x, int y, int age) {
this.age = age;
this.x = x;
this.y = y;
}
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;
}
}
생명체는 나이가 들고, 이동할 수 있는 공통적인 특성을 가지므로 하위 클래스에서 상속 할 수 있도록 일반 메서드로 구현 합니다.
public void age() {
age++;
}
public void move(int xDistance) {
x += xDistance;
}
공격 기능과 정보출력 기능은 각 생명체에게 필요한 기능 이지만 생명체에 따라 다르게 구현하기 위해 구체적인 기능은 하위 클래스에서 처리 하도록 추상메서드로 선언합니다.
public abstract void attack();
public abstract void printInfo();
2. Animal(동물) 추상클래스
동물은 생명체이기 때문에 Creature 추상클래스를 상속 받고 attack() 메소드를 오버라이딩을 통해 구현해줍니다.
printInfo()는 왜 없을까요?
각 생명체마다 정보가 다르고, Animal 클래스 또한 추상 클래스 이기 때문에 하나 더 내려 상위 클래스에서 선언한 추상 메서드를 앞으로 동물 클래스를 상속할 클래스에게 위임 하는 것입니다.
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("몸을 사용하여 공격!!");
}
}
3. Talkable 인터페이스
인간은 말을 할 수 있으므로 추상메서드를 하나 가진 인터페이스를 생성합니다.
public interface Talkable {
abstract void talk();
}
4. Human(인간) 추상클래스
Human(인간) 클래스도 Animal(동물) 클래스와 마찬가지로 attack() 추상 메서드는 오버라이딩 해주고,
인간은 말을 할 수 있으므로 Talkable 클래스를 implements 하여 talk() 추상 메서드를 오버라이딩 해줍니다.
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("사람은 말을 할 수 있다.");
}
}
5. Flyable 인터페이스
날 수 있는 동물에 구현시킬 Flyable 인터페이스 입니다. 다른 동물들과 다르게 y행으로 위로 올라 갈 수 있도록 하는 메서드들을 선언했습니다.
public interface Flyable {
void fly(int yDistance);
void flyMove(int xDistance, int yDistance);
}
6. Pigeon(비둘기) 일반클래스
Animal(동물) 클래스를 상속하고, 날 수 있는 동물이기 때문에 Flayable 인터페이스를 implements 하여 해당 메서드들을 오버라이딩 합니다.
그리고 여기에 Creature(생명체) 클래스의 추상 메서드인 printInfo() 까지 오버라이딩 해줍니다.
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() {
System.out.println("Pigeon -> " + toString());
}
}
7. Swimable 인터페이스
수영 할 수 있는 동물 , 인간에 구현 시킬 인터페이스 입니다.
public interface Swimable {
void swimDown(int yDistance);
}
8. Turtle(거북이) 일반클래스
Swimable 클래스를 implements 해서 swimDown(), printInfo() 를 오버라이딩 합니다.
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());
}
}
9. Programmer 인터페이스
코딩을 할 수 있는 인간에 구현시킬 인터페이스 입니다.
public interface Programmer {
void coding();
}
10. Kevin(인간이름) 일반클래스
Kevin은 인간이고 수영, 코딩을 할 수 있으므로 Programmer와 Swimable를 implements 하여 오버라이딩 합니다.
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());
}
}
11. 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();
}
}
Reference : https://inpa.tistory.com/entry/JAVA-☕-인터페이스-vs-추상클래스-차이점-완벽-이해하기
https://myjamong.tistory.com/150
다중상속
https://readystory.tistory.com/112