abstract include interface
추상클래스는 미완성 된 설계도 같은 의미이다. 그래서 추상클래스로는 인스턴스를 만들 수 없기 때문에(설계도만 가지고 무엇을 만들 수 없다.) 자손클래스로부터 상속으로 인해 만들어 질 수 있다.
Ex) 어떤 것을 만들 때 맨땅에 헤딩 보다는 설계도를 가지고 대충 틀을 잡아놓고 시작하는 것이 좋을 것이다. 대충 이정도만 알아두자.
추상클래스 표준
Abstract class classname{
…
}
추상클래스를 선언하는 이유는 클래스마다 각자 다른 기능을 할 수 있기 때문에 간단히 조상클래스에서 선언만을 해주고 자손클래스에서 기능을 설정해주어 정확한 구현을 할 수 있게 해주어야한다.
/* 주석을 적는 칸*/
Abstract class classname{
…
}
그래서 상속받은 자손클래스는 그 추상클래스에 대해서 구현부에 오버라이딩을 통하여 메서드 구현을 해주어야만 한다. 하지 않게되면 그 자손클래스에서도 추상클래스로 지정해주어야한다.
특히 메서드를 적을 때 선언부를 잘 적어주어야한다. 선언부만 잘적어도 메서드 반은 완성됐다고 봐도된다.
abstract class Player{
boolean pause;
int currentpos;
Player(){//추상클래스도 생성자가 필요하다.
pause=false;
currentpos=0;
}
/*지정된 음악을 재생하는 메서드*/
abstract void play(int pos);
/*재생을 즉시 멈추는 메서드 작성*/
abstract void stop();
//play() 추상메서드를 이렇게 빈칸에 적어도 된다. 적는 순간 일반메서드로 간주되기 때문.
void play() {
play(currentpos);
}
void pause() {
if(pause) {
pause=false;
play(currentpos);
}else {
pause=true;
stop();
}
}
}
class cdplayer extends Player{
void play(int currentpos) {
/*조상의 추상메서드를 구현. 내용 생략*/
}
void stop() {
/*조상의 추상메서드를 구현. 내용 생략*/
}
}
public class abstracttest {
public static void main(String[] args) {
//...
}
}
pasue 라는 상태를 표시해주는 변수와 currentpos라는 어디서 시작되는지에 대한 표시를 해주는 변수를 선언.
플레이어라는 추상클래스에 대한 생성자 메서드 작성 ( 추상클래스도 생성자가 필요)
play와 stop 이라는 추상클래스에 대한 추상메서드 ; 어느 곳에서나 쓰여야하는 메서드 ;
play라는 일반 메서드와 pause 라는 일반메서드 안에서 추상메서드를 적었는데 저렇게 써도 된다.
그리고 player 클래스를 상속받은 cdplayer 의 클래스에서 추상메서드를 이용해서 오버라이딩.
인터페이스는 추상클래스보다는 추상화 정도가 높아서 추상클래스에서 몸통을 갖춘 일반 메서드 또는 멤버변수를 구성원으로 가졌다면 인터페이스는 추상메서드와 상수만을 멤버로 가질 수 있다.
인터페이스도 불완전하기 때문에 도움을 줄만한 목적으로 사용한다.
인터페이스 선언 방법
Interface INTERFACENAME{
public static final type name = value;
public abstract methodname (variablelist);
}
모든 멤버변수는 public static final 이어야 하며 생략가능하고, 모든 메서드는 public abstract 이어야 한다.
인터페이스 안에 public static final name = value ; 이 선언이 final int name= value, int name=value, static int name=value 이렇게 제어자들이 빠져도 상관 없다. 컴파일시에 자동으로 추가 된다. (추상메서드의 선언도 마찬가지이다.)
interface Movalble{
/*지정된 위치(x,y)로 이동하는 기능의 메서드*/
void move(int x,int y);
}
interface Attackable{
/*지정된 대상(u)를 공격하는 기능의 메서드*/
void move(int x,int y); //위 인터페이스와 같이 컴파일 과정에서 public abstract 가 자동으로 붙는다.
}
interface Figthtable extends Movalble, Attackable{}
//이곳에서는 정의된 멤버가 아무것도 없지만 조상인터페이스로부터 상속받은 두개의 추상메서드를 멤버로 갖게된다.
인터페이스도 자체적으로 인스턴스를 생성할 수 없어서 추상클래스가 상속을 통해 추상메서드를 완성하는 것처럼, 인터페이스도 자신에 정의된 추상메서드의 몸통을 만들어주는 클래스를 작성해야하는데, 그 방법은 추상클래스가 자신을 상속받는 클래스를 정의하는 것과 다르지 않다. 다만 클래스는 확장한다는 의미의 키워드 extends 를 사용하지만 인터페이슨느 구현한다는 의미의 키워드 implements를 사용한다.
예제
interface Fightable extends Movable,Attackable{} //extends 인터페이스에서 참조하는 다른 인터페이스
//단 , class에서 상속받을 때는 implements
interface Movable {void move(int x, int y);}
interface Attackable {void attack(Unit u);}
//위 인터페이스들은 메서드앞에 public abstract가 컴파일 시에 붙게 되었다.
class Unit{
int currentHP; //유닛의 체력
int x; //유닛의 x좌표
int y; //유닛의 y좌표
}
class Fighter extends Unit implements Fightable{
public void move(int x, int y) {/*생략*/}
public void attack(Unit u) {/*생략*/}//오버라이딩 비슷
}
public class interfacetest {
public static void main(String[] args) {
Fighter f = new Fighter();
if (f instanceof Unit) {
System.out.println("f는 Unit 자손임");
}
if (f instanceof Fightable) {
System.out.println("f는 Fightable 인터페이스를 구현함");
}
if (f instanceof Movable) {
System.out.println("f는 Movable 인터페이스를 구현함");
}
if (f instanceof Attackable) {
System.out.println("f는 Attackable 인터페이스를 구현함");
}
}
}
결과
과제 인터페이스의 상속 구성도 그리기