Java 09. 객체지향 프로그래밍 Ⅱ 추상화 - swkim0128/PARA GitHub Wiki


type: Java archive: false

추상클래스(abstract class)

추상클래스란?


클래스를 설계도에 비유한다면, 추상클래스는 미완성 설계도에 비유할 수 있다. 클래스가 미완성이라는 것은 멤버의 개수에 관계된 것이 아니라, 단지 미완성 메서드(추상메서드)를 포함하고 있다는 의미.

미완성 설계도로 완성된 제품을 만들 수 없듯이 추상클래스로 인스턴스는 생성할 수 없다 추상클래스는 상속을 통해서 자손클래스에 의해서만 완성될 수 있다.

abstract class 클래스이름 {
....
}

추상메서드(abstract method)


메서드는 선언부와 구현부(몸통)으로 구성되어 있ㅅ다고 했다. 선언부만 작성하고 구현부는 작성하지 않은 채로 남겨 둔 것이 추상메서드이다.

/* 주석을 통해 어떤 기능을 수행할 목적으로 작성하였는지 설명한다. */
abstract 리턴타입 메서드이름();

추상클래스로부터 상복받은 자손클래슨느 오버라이딩을 통해 조상인 추상클래스의 추상메서들르 모두 구현해주어야 한다. 만일 조상으로부터 상복받은 추상메서드 중 하나라도 구현하지 않는다면, 자손클래스 역시 추상클래스로 지정해 주어야 한다.

abstract class Player { // 추상클래스
	abstract void play(int pos);    // 추상메서드
	abstract void stop();    // 추상메서드
}

class AudioPlayer extends Player {
	void play(int pos) { /* 내용 생략 */ }    // 추상메서드를 구현
	void stop() { /* 내용 생략 */ }    // 추상메서드를 구현
}

abstract class AbstractPlayer extends Player {
	void play(int pos) { /* 내용생략 */ }    // 추상메서드를 구현

추상클래스의 작성


여러 클래스에 공통적으로 사용될 수 있는 클래스를 바로 작성하기도 하고, 기존의 클래스의 공통적인 부분을 뽑아서 추상클래스로 만들어 상속하도록 하는 경우도 있다.

상속이 자손 클래스를 만드는데 조상클래스를 사용하는 것이라면, 이와 반대로 추상화는 기존의 클래스의 공통부분을 뽑아내서 조상 클래스를 만드는 것이라고 할 수 있다.

추상화 - 클래스간의 공통점을 찾아내서 공통의 조상을 만드는 작업
구체화 - 상속을 통해 클래스를 구현, 확장하는 작업

인터페이스(interface)


인터페이스는 일종의 추상클래스이다. 인터페이스는 추상클래스처럼 추상메서드를 갖지만 추상클래스보다 추상화 정도가 높아서 추상클래스와 달리 몸통을 갖춘 일만 메서드 또는 멤버변수를 구성원으로 가질 수 없다. 오직 추상메서드와 상수만을 멤버로 가질 수 있으며, 그 외의 다른 어떠한 요소도 허용하지 않는다.

인터페이스의 작성


interface 인터페이스이름 {
	public static final 타입 상수이름 = ;
	public abstract 메서드이름(매개변수 목록);
}
  • 모든 멤버변수는 public static final 이어야하며, 이를 생략할 수 있다.
  • 모든 메서드는 public abstract 이어야 하며, 이를 생략할 수 있다.
interface PlayingCard {
	public static final int SPACE = 4;
	final int DIAMOND = 3;        // public static final int DIAMOND = 3;
	static int HEART = 2;         // public static final int HEART = 2;
	int CLOVER = 1;               // public static final int CLOVER = 1;


	public abstract Sring getCardNumber();
	String getCardKind();       // public abstract String getCardKind();
}

인터페이스의 상속


인터페이스는 인터페이스로부터만 상속받을 수 있으며, 클래스와 달리 다중상속, 즉 여러 개의 인터페이스로부터 상속을 받는 것이 가능하다.

interface Movalbe {
	/** 지정된 위치 (x, y)로 이동하는 기능의 메서드 */
	void move(int x, int y);
}

interface Attackable {
	/** 지정된 대상(u)를 공격하는 기능의 메서드 */
	void attack(Unit u);
}

interface Fightable extends Movable, Attackable ()

인터페이스의 구현


인터페이스도 추상클래스처럼 그 자체로는 인스턴스를 생성할 수 없으며, 추상클래스가 상속을 통해 추상메서드를 완성하는 것처럼, 인터페이스도 자신에 정의된 추상메서드의 몸통을 만들어주는 클래스를 작성해야한다.

class 클래스이름 implements 인터페이스 이름 {
	// 인터페이스에 정의된 추상메서드를 구현해야한다.
}

class Fighter implements Fightable {
	public void move(int x, int y) { /* 내용 생략 */ }
	public void attack(Unit u) { /* 내용 생략 */ }
}

만일 구현하는 인터페이스의 메서드 중 일부만 구현한다면, 추상클래스로 선언되어야 한다.

abstract class Fighter implements Fightable {
	public void move(int x, int y) { /* 내용 생략 */ }
}

인터페이스를 이용한 다중상속


인터페이스는 상수만 정의할 수 있으므로 조상클래스의 멤버변수와 충돌하는 경우는 극히 드물고 추상메서드는 구현내용이 전혀 없으므로 조상클래스의 메서드와 선언부가 일치하는 경우에는 당연히 조상클래스쪽의 메서드를 상속받으면 되므로 문제되지 않는다.
이렇게 하면 상속받는 멤버의 충돌은 피할 수 있지만, 다중상속의 장점을 잃게 된다. 만일 두 개의 클래스로부터 상속을 받아야 할 상황이라면, 두 조상클래스 중에서 비중이 높은 쪽을 선택하고 다른 한쪽은 클래스 내부에 멤버로 포함시키는 방식으로 처리하거나 어느 한쪽의 필요한 부분을 뽑아서 인터페이스로 만든 다음 구현하도록 한다.

인터페이스를 이용한 다형성


다형셩에 대해 학습할 때 자손클래스의 인스턴스를 조상타입의 참조변수로 참조하는 것이 가능하다는 것을 배웠다.
인터페이스 역시 이를 구현한 클래스의 조상이라 할 수 있으므로 해당 인터페이스 타입의 참조변수로 이를 구현한 클래스의 인스턴스를 참조할 수 있으며, 인터페이스 타입으로의 형변환도 가능하다.

Fightable f = (Fightable)new Fighter();
또는
Fightable f = new Fighter();

따라서 인터페이스는 다음과 같이 메서드의 매개변수의 타입으로 사용될 수 있다.

void attack(Fightable f) {
// ...
}

인터페이스 타입의 매개변수가 갖는 의미는 메서드 호출 시 해당 인터페이스를 구현한 클래스의 인스턴스를 매개변수로 제공해야한다는 것이다.
그래서 attack 메서드를 호출할 때는 매개변수로 fightable인터페이스를 구현한 클래스의 인스턴를스 넘겨주어야 한다.

그리고 다음과 같이 메서드의 리턴타입으로 인터페이스의 타입을 지정하는 것 역시 가능하다.

fightable method() {
// ...
return new Fighter();
}

인터페이스의 장점


  • 개발시간을 단축시킬 수 있다.
  • 표준화가 가능하다.
  • 서로 관계없는 클래스들에게 관계를 맺어 줄 수 있다.
  • 독립적인 프로그래밍이 가능하다.
  1. 개발시간을 단축시킬 수 있다.

    일단 인터페이스가 작성되면, 이를 사용해서 프로그램을 작성하는 것이 가능하다. 메서드를 호출하는 쪽에서는 메서드의 내요에 관계없이 선언부만 알면 되기 때문이다.
    그리고 동시에 다른 한 쪽에서는 인터페이슬 구현하는 클래스를 작서하도록 하여, 인터페이스를 구현하는 클래스가 작성될 때까지 기다리지 않고도 양쪽에서 동시에 개발을 진행할 수 있다.

  2. 표준화가 가능하다.

    프로젝트에 사용되는 기본 틀을 인터페이스로 작성한 다음, 개발자들에게 인터페이스를 구현하여 프로그램을 작성하도록 함으로써 보다 일관되고 정형화된 프로그램의 개발이 가능하다.

  3. 서로 관계없는 클래스들에게 관계를 맺어 줄 수 있다.

    서로 상속관계에 있지도 않고, 같은 조상클래스를 가지고 있지 않은 서로 아무런 관계도 없는 클래스들에게 하나의 인터페이스를 공통적으로 구현하도록 함으로써 관계를 맺어 줄 수 있다.

  4. 독립적인 프로그래밍이 가능하다.

    인터페이스를 이용하면 클래스의 선언과 구현을 분리시킬 수 있기 때문에 실제 구현에 독립적인 프로그램을 작성하는 것이 가능하다. 클래스와 클래스간의 직접적인 관계를 인터페이스를 이용해서 간접적인 관계로 변경하면, 한 클래스의 변경이 관련된 다른 클래스에 영향을 미치지 않는 독립적인 프로그래밍이 가능하다.

인터페이스의 이해


  • 클래스는 사용하는 쪽(User)과 클래스를 제공하는 쪽(Provider)이 있다.
  • 메서드를 사용(호출)하는 쪽(User)에서는 사용하려는 메서드(Provider)의 선언부만 알면된다.(내용은 몰라도 된다.)

클래스 A가 클래스 B를 직접 호출하지 않고 인터페이스를 매개체로 해서 클래스 A가 인터페이스를 통해서 클래스 B의 메서드에 접근하도록 하면, 클래스 B에 변경사항이 생기거나 클래스 B와 같은 기능의 다른 클래스로 대체 되어도 클래스 A는 전혀 영향을 받지 않도록 하는 것이 가능하다.

⚠️ **GitHub.com Fallback** ⚠️