[2023.08.21] 추상 클래스와 인터페이스

이재하·2023년 8월 20일
1

항해99

목록 보기
25/48
post-custom-banner

추상 클래스 (abstract class)

미완성 메소드를 갖고 있는 클래스

abstract class Player { 		  // 추상클래스(미완성 클래스)
	abstract void play(int pos);  // 추상메소드(몸통 { } 이 없는 미완성 메소드)
    abstract void stop(); 		  // 추상메소드
}
  • 다른 클래스 작성에 도움을 주기 위한 것. 인스턴스 생성 불가
    Player p = new Player(); // 에러. 추상클래스의 인스턴스 생성 불가

  • 상속을 통해 추상 메소드를 완성해야 인스턴스 생성가능

// 상속을 통해 완성된 메소드
class AudioPlayer entends Player {
	void play(int pos) { /* 내용 생략 */ } // 추상메소드를 구현
    void stop() { /* 내용 생략 */ }		 // 추상메소드를 구현
}
  • 인스턴스 생성이 가능해진다.

상속된 자손의 메소드를 완성하면
조상타입 Player도 사용가능하다.
Player.p 를 호출해도 자손타입 메소드가 실행된다.

AudioPlayer ap = new AudioPlayer();	// Ok
Player p = new AudioPlayer();		// Ok

추상 메소드 (abstract method)

abstract 리턴타입 메소드이름();

  • 미완성 메소드.
  • 구현부가 없는 메소드

꼭 필요하지만 자손마다 다르게 구현될 것으로 예상되는 경우 사용된다.

abstract class AbstractPlayer extends Player {
	void play(int pos) { /* 내용 생략 */ } // 추상메소드를 구현
//  abstract void stop(); 도 상속이 됐기 때문에 class 앞에 abstract를 붙여야 함
}

AbstractPlayer class는 Player class에서 받아 2개의 추상 메소드를 상속 받았지만 메소드를 1개밖에 구현하지 않아 abstract class이다. 따라서 class 에 abstract 를 붙여야함.
그렇지 않으면 에러가 발생한다.
필요에 따라서 추상클래스를 상속받아서 추상메소드를 전부 구현해도, 안해도된다.

추상메소드를 호출 할 수 있는 이유는 나중에 상속을 통해서 자손이 완성할 수 있기 때문.
추상클래스라 인스턴스 생성 불가이기 때문에 호출하는 코드가 있어도 호출되지 않음.
상속을 통해 자손이 추상 메소드를 완성하고 자손객체를 생성하면 그 때 호출된다.


추상클래스의 작성

  • 여러 클래스에 공통적으로 사용될 수 있는 추상클래스를 바로 작성하거나
    기존 클래스의 공통 부분을 뽑아서 추상클래스를 만든다.
public class Ex7_10 {
	public static void main(String[] args) {
		Unit[] group = { new Marine(), new Tank(), new Dropship() };
        
//		  아래 네개의 코드를 위의 하나의 코드로 줄일 수 있다.
//        Unit[] group = new Unit[3]; 
//        group[0] = new Marine();
//        group[1] = new Tank();
//        group[2] = new Dropship();

		for (int i = 0; i < group.length; i++)
			group[i].move(100, 200);
	}
}

abstract class Unit {
	int x, y;
	abstract void move(int x, int y);
	void stop() { /* 현재 위치에 정지 */ }
}

class Marine extends Unit { // 보병
	void move(int x, int y) {
		System.out.println("Marine[x=" + x + ",y=" + y + "]");
	}
	void stimPack() { /* 스팀팩을 사용한다. */ }
}

class Tank extends Unit { // 탱크
	void move(int x, int y) {
		System.out.println("Tank[x=" + x + ",y=" + y + "]");
	}
	void changeMode() { /* 공격모드를 변환한다. */ }
}

class Dropship extends Unit { // 수송선
	void move(int x, int y) {
		System.out.println("Dropship[x=" + x + ",y=" + y + "]");
	}
	void load()   { /* 선택된 대상을 태운다. */ }
	void unload() { /* 선택된 대상을 내린다. */ }
}

공통 부분을 추출해서 Unit 클래스로 정의 ->
나머지 클래스들은 Unit 클래스를 상속 받고 코드들이 간결해짐 (코드의 중복 제거)

인터페이스

  • 추상 메소드의 집합
  • 모든 멤버변수는 public static final, 생략 가능
  • 모든 메소드는 public abstract, 생략 가능
    상수와 추상메소드만 가질 수 있고 iv, 생성자, 인스턴스 메소드 다 가질 수 없다.
  • 디폴트 메소드와 static 메소드 추가 가능
// 인터페이스 선언

interface 인터페이스이름 {
	public static final 타입 상수이름 =;
    public abstract 메소드이름(매개변수목록);
}
  • 예제
interface PlayingCard {
	public static final int SPADE = 4;
    final int DIAMOND = 3;	// public static final int DIAMOND = 3;
    static int HEAR = 2;	// public static final int HEART = 2;
    int CLOVER = 1;			// public static final int CLOVER = 1;
    // 상수는 항상 public static final 이라 일부 생략 가능
    
    public abstract String getCardNumber();
    String getCardKind();	// public abstract String get CardKind();
    // 위와 같이 인터페이스이 추상 메소드는 public abstract 여서 생략 가능
}

인터페이스의 상속

  • 인터페이스의 조상은 인터페이스만 가능
  • 다중 상속이 가능 (추상메소드는 충돌해도 문제 없음)
interface Fightabl extends Movable, Attackable { }

interface Moveable {
	void move(int x, int y);
}

interface Attackable {
	void attack(Unit u);
}

인터페이스의 구현

  • 인터페이스에 정의된 추상 메소드를 완성하는 것
class 클래스이름 implements 인터페이스이름 {
	// 인터페이스에 정의된 추상메소드를 모두 구현해야 함
}

예제

interface Fightable {
	void move (int x, int y);
    void attack (Unit u);
}

class Fighter. implements Fightable {
	public void move (int x, int y) { /* 메소드 구현 */ }
    public void attack (Unit u) { /* 메소드 구현 */ }
}

// 일부만 구현하는 경우, 클래스 앞에 abstract 를 붙여야 함

abstract class Fighter implements Fightable {
	public void move (int x, int y) { /* 메소드 구현 */ }
//  public abstract void attack (Unit u);
}

인터페이스와 다형성

post-custom-banner

0개의 댓글