추상 메서드가 하나이상 존재하는 클래스는 추상 클래스
로 지정해야된다
abstract class Animal{
public abstract void move(); // 함수의 Body를 구현하지 않음.
}
class Lion extends Animal{
@Override
public void move(){
System.out.println("사자의 move 메서드입니다.");
}
}
public class HelloWorld{
public static void main(String[] args){
Lion lion = new Lion();
lion.move(); // 사자의 move 메서드입니다.
}
}
추상 메소드(=추상 클래스)를 사용한 이유는 자손이 구현해야 할 메소드를 암묵적으로 강제한 것이다.
따라서 Animal 클래스를 상속받는 클래스(Lion)의 경우 꼭 move()
함수를 @Override해야만 한다.
추상 클래스 | 인터페이스 |
---|---|
생성자 o | 생성자 x |
변수 가질 수 o | 변수 가질 수x (상수만 가질 수 o) |
일반 메서드 가질 수 o | 일반 메서드 가질 수 o |
추상 메서드 가질 수 o | 추상 메서드 가질 수 o (추상 메서드만 가질 수 o) |
추상 메서드의 집합
!interface Printable { // MS가 정의하고 제공한 인터페이스
public abstract void print(String doc);
}
class SPrintDriver implements Printable{ // 삼성이 구현한 것
@Override
public void print(Strui)
}
public class DriverTest{ // 사용자가 삼성 사용하는 것
public static void main(String[] args){
// 2. 객체 생성 불가능 BUT 참조변수 선언은 가능o (다형성)
Printable p = new SPrintDriver(); 가능
~~Printable p = new Printable(); 불가능~~
}
}
인터페이스 안에서 일반 메서드(Body를 가진)를 default
키워드를 통해서 선언할 수 있게 했다.
사실 인터페이스는 기능에 대한 구현보다는, 기능에 대한 '선언'에 초점을 맞추어서 사용 하는데, default 메서드는 왜 등장했을까?
"하위 호환성"때문이다. 예를 들어 설명하자면, 여러분들이 만약 오픈 소스코드를 만들었다고 가정하자. 그 오픈소스가 엄청 유명해져서 전 세계 사람들이 다 사용하고 있는데, 인터페이스에 새로운 메서드를 만들어야 하는 상황이 발생했다. 자칫 잘못하면 내가 만든 오픈소스를 사용한 사람들은 전부 오류가 발생하고 수정을 해야 하는 일이 발생할 수도 있다. 이럴 때 사용하는 것이 바로 default 메소드다.
(참고: 자바 기본서인 '자바의 신'에서 발췌한 내용입니다)
만약, 기존에 존재하던 인터페이스를 이용하여서 구현된 클래스를 만들고 사용하고 있는데 인터페이스를 보완하는 과정에서 추가적으로 구현해야 할 혹은 필수적으로 존재해야 할 메서드가 있다면 이미 이 인터페이스를 구현한 클래스와의 호환성이 떨어 지게 된다. 이러한 경우 default 메서드를 추가하게 된다면 하위 호환성은 유지되고 인터페이스의 보완을 진행 할 수 있다.
interface MyInterface {
defaultvoidprintHello() {
System.out.println("Hello World");
}
}
class MyClass implements MyInterface { }
public class DefaultMethod {
publicstaticvoidmain(String[] args) {
MyClass myClass =new MyClass();
myClass.printHello();// Hello World
}
}