Programming/JAVA

abstract include interface

gyu0 2020. 6. 27. 21:20

 

추상클래스는 미완성 된 설계도 같은 의미이다. 그래서 추상클래스로는 인스턴스를 만들 수 없기 때문에(설계도만 가지고 무엇을 만들 수 없다.) 자손클래스로부터 상속으로 인해 만들어 질 수 있다.

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 인터페이스를 구현함");
		}	
	}
}

결과

 

과제 인터페이스의 상속 구성도 그리기