2020. 6. 26. 11:20ㆍ정리/JAVA
인터페이스와 추상클래스의 공통점
인터페이스와 추상클래스의 공통점은
- 추상화에 사용된다.
- 구현 객체에 독립적인 메소드 제공이 가능하다.
- 메소드의 선언만 있고 구현 내용은 없다.
- 자기 자신을 직접 인스턴스 생성할 수 없다.
- 상속 또는 구현을 통해 객체를 생성할 수 있다.
가 있다.
하나씩 살펴보도록 하겠다.
추상화
public Class CarA {
public void 운전하다() {
System.out.println("Car A를 운전합니다.");
}
public void 주차하다() {
System.out.println("Car A를 주차합니다.");
}
}
public Class CarB {
public void 운전() {
System.out.println("Car B를 운전합니다.");
}
public void 주차() {
System.out.println("Car B를 주차합니다.");
}
}
위와 같이 차와 관련된 두 개의 클래스가 있다고 가정할 시
두 개의 클래스는 모두 차로 할 수 있는 행위를 표현하지만 메소드 명이 살짝 다르기 때문에 CarA를 사용했다가 CarB로 변경한다면 어쩔 수 없이 코드의 수정이 필요할 것이다.
public class test {
public static void main(String[] args) {
CarA a = new CarA(); // CarB a = new CarB();
a.운전하다(); // a.운전();
a.주차하다(); // a.주차();
}
}
CarA에서 CarB를 사용하고자 한다면 운전하다()를 운전()으로, 주차하다()를 주차()로 변경해야한다.
이를 해결하기 위해 객체들간의 공통적이고 핵심적인 기능을 추출하여 상위 클래스로 만들어 대상을 일반화한다면 최소한의 코드 수정으로 해결할 수 있다.
pubilc interface Car() {
public void 운전하다();
public void 주차하다():
}
public abstract class Car {
public abstract void 운전하다();
public abstract void 주차하다();
}
위의 인터페이스나 추상클래스를 구현 또는 상속해 CarA와 CarB 클래스를 정의한다면 변경 시 코드 수정을 최소화할 수 있고, 어떤 차종류가 되었던 일정한 메소드로 기능을 사용할 수 있기 때문에 협업에도 용이할 것이다.
독립적인 메소드 제공
pubilc interface Car() {
public void 운전하다();
public void 주차하다();
default void 특별기능() {
System.out.println("차의 특별기능");
}
}
public abstract class Car {
public abstract void 운전하다();
public abstract void 주차하다();
public void 특별기능() {
System.out.println("차의 특별기능");
}
}
인터페이스는 디폴드메소드로, 추상클래스는 일반적인 메소드를 통해 독립적인 메소드를 제공할 수 있다.
이 메소드는 구현 또는 상속한 클래스를 정의할 때 필요에 따라 오버라이딩 유무를 선택할 수 있다.
메소드의 구현부가 없음
pubilc interface Car() {
public void 운전하다();
public void 주차하다():
}
public abstract class Car {
public abstract void 운전하다();
public abstract void 주차하다();
}
하위 클래스에서 무조건 오버라이딩해야하는 메소드는 모두 추상메소드이므로, 메소드의 구현부는 없다.
다만 인터페이스의 경우 디폴트 메소드나 정적 메소드, 추상클래스의 경우 일반 메소드는 여기에 해당되지 않는다.
자기 자신을 직접 인스턴스 생성할 수 없음
해당 타입을 인스턴스화 할 수 없다는 동일한 오류가 발생한다.
상속 또는 구현을 통해 사용 가능
public Class CarA implements Car{
@Override
public void 운전하다() {
System.out.println("Car A를 운전합니다.");
}
@Override
public void 주차하다() {
System.out.println("Car A를 주차합니다.");
}
}
public Class CarB extends Car {
@Override
public void 운전() {
System.out.println("Car B를 운전합니다.");
}
@Override
public void 주차() {
System.out.println("Car B를 주차합니다.");
}
}
인터페이스는 구현(implements), 추상클래스는 상속(extends)로 사용할 수 있다.
이는 인터페이스나 추상클래스나 모두 자기자신을 인스턴스화해서 직접 사용할 수 없기 때문이다.
인터페이스와 추상클래스의 차이점
인터페이스와 추상클래스의 차이점은
- 키워드
- 메소드 오버라이딩
- 생성자
- 제약사항
- 다중 상속, 다중 구현
이 있다.
마찬가지로 하나씩 살펴보도록 하겠다.
키워드
pubilc interface Car() {
public void 운전하다();
public void 주차하다():
}
public abstract class Car {
public abstract void 운전하다();
public abstract void 주차하다();
}
인터페이스와 추상클래스를 선언할 때 사용하는 키워드가 서로 다르다.
인터페이스는 interface를 사용하며, 인터페이스 선언 이외에는 사용되지 않는다.
추상클래스는 abstract를 사용하며, 이는 기타제어자로 추상클래스 선언 외에도 다양하게 사용된다.
메소드 오버라이딩
pubilc interface Car() {
public void 운전하다();
public void 주차하다():
}
public Class CarA implements Car{
@Override
public void 운전하다() {
System.out.println("Car A를 운전합니다.");
}
@Override
public void 주차하다() {
System.out.println("Car A를 주차합니다.");
}
}
인터페이스를 구현했다면 어떤 경우라도 무조건 오버라이딩을 해야한다.
public abstract class A {
public abstract void abstractMethod();
}
public abstract class Aa extends A {
}
public class Aaa extends Aa {
@Override
public void abstractMethod() {
System.out.println("A 추상클래스의 추상메소드");
}
}
추상 클래스의 경우 추상 클래스를 상속받은 클래스가 동일하게 추상 클래스인 경우 어처피 그 클래스를 사용하기 위해서는 또다시 상속을 해야 하기 때문에 굳이 추상메소드를 오버라이딩 하지 않아도 된다.
이 경우 일반적인 하위 클래스가 추상 클래스를 상속받았을 때에 추상메소드를 모두 오버라이딩 하게 된다.
생성자
public abstract class Abstract {
String s = "";
public Abstract(String s) {
this.s = s;
}
}
인터페이스는 생성자를 선언하지 못하지만, 추상클래스는 클래스의 일종이기 때문에 생성자를 선언할 수 있다.
다만 생성자를 선언한다고 하더라도 인스턴스화는 하지 못한다.
그렇기 때문에 추상클래스를 상속받은 하위 클래스에서 필드를 초기화할 때 사용한다.
public class Extends extends Abstract {
public Extends(String s) {
super(s);
}
}
제약사항
인터페이스의 제어자는 public과 abstract만 가능하다.
이는 인터페이스가 어쨌든간 구현이 되어야 사용이 가능하며, 구현의 범위를 좁히지 않게 하기 위함이다.
인터페이스의 메소드는 public, abstract, default, static, strictfp(Strict Floating Point, 엄격한 부동소수점 제한자)만 가능하다.
추상 메소드는 public과 protected만 가능한것에 비해 인터페이스는 그 특이함 때문에 어려가지 제한자를 추가할 수는 있다.
인터페이스의 필드는 public이나 static & final을 같이 사용하는 경우만 가능하다.
인터페이스의 필드는 무조건 상수처리되기 때문이며, public 을 붙이면 public static final과 동일하게 취급되기 때문이다.
추상클래스의 경우 public이나 abstract & final을 동시에 사용해야만 한다.
인터페이스와 유사하게 추상클래스를 사용하기 위해서는 상속을 진행해야 하기 때문이다.
다중 상속, 다중 구현
추상클래스는 다중상속이 불가능하다.
인터페이스는 다중구현이 가능하다.
그렇기 때문에 인터페이스를 사용하는 것이 추상클래스를 사용하는 것보다 유연한 대처가 가능하다.
A라는 인터페이스를 구현한 클래스가 다른 인터페이스를 동시에 구현하거나 다른 클래스를 상속받는게 가능한데 비해
추상클래스는 한 번에 하나의 클래스만 상속받을 수 있기 때문이다.
인터페이스의 역할을 추상클래스로 대처할 경우 추상클래스를 상속받은 클래스가 다른 클래스 또한 상속받을 필요가 있을 경우 상속관계가 복잡해지기 때문이다.
해당 글은 개인이 공부하면서 정리한 글이기 때문에 정확하지 않은 내용이 있을 수 있습니다.