JAVA(다형성, abstract, interface)

다형성(polymorphism)

  • 하나의 객체가 여러가지 타입을 가질 수 있는 것을 의미
  • 자바에서는 한 타입의 참조변수로 여러 타입의 객체를 참조할 수 있도록 함으로써 다형성을 프로그램적으로 구현
  • 조상타입의 참조변수로 자손타입의 객체를 다룰 수 있는 것
  • 자손타입의 참조변수로 조상타입의 인스턴스를 참조할 수는 없다.
class Parent { ... }
class Child extends Parent { ... }

Parent pa = new Parent(); // 허용
Child ch = new Child();   // 허용
Parent pc = new Child();  // 허용
Child cp = new Parent();  // 오류 발생.

예제

class Tv{
    boolean power;	// 전원상태(on/of)
    int channel;	// 채널
    
    void power()    	{ power = !power; }
    void channelUp()	{ ++channel; }
    void channelDown()	{ --channel; }
}

class CaptionTv extends Tv {
    String text;   // 캡션을 보여주기 위한 문자열
    void caption() { /* 내용 생략 */ }
}
CaptionTv c = new CationTv();
Tv        t = new CationTv();

위처럼 CationTv인스턴스 2개를 생성하고 참조변수 c와 t가 생성된 인스턴스를 하나씩 참조하도록 하였다.

두 참조변수의 차이점은 인스턴스가 CaptionTv타입이라 할지라도, 참조변수 t로 CaptionTv인스턴스의 모든 멤버를 사용할 수 없다.

조상 클래스에서 상속을 받아 오버라이팅된 메서드만 사용이 가능하고, 오버라이팅된 메서드로 실행된다.

형변환

  • 서로 상속관계에 있는 클래스 사이에만 타입 변환을 할 수 있습니다.
  • 자식 클래스 타입에서 부모 클래스 타입으로의 타입 변환은 생략 할 수 있습니다.
  • 부모 클래스 타입에서 자식 클래스 타입으로의 타입 변환은 반드시 명시해야 한다.
class Parent { ... }
class Child extends Parent { ... }
class Brother extends Parent { ... }

Parent pa1 = new Parent();
Parent pa2 = null;
Child ch = new Child();
Child br = null;

pa2 = ch;           // 타입 변환을 생략할 수 있음.
br = (Brother)pa1;  // 타입 변환을 생략할 수 없음.
br = (Brother)ch;   // 직접적인 상속 관계가 아니므로, 오류 발생.

abstract

추상 클래스

  • 클래스가 설계도라면 추상클래스는 '미완성 설계도'이다.
  • 추상메서드(미완성 메서드)를 포함하고 있는 클래스
  • 완성된 설계도가 아니므로 인스턴스를 생성할 수 없다.

추상 메서드

  • 선언부만 있고 구현부(기능, 몸통)가 없는 메서드
  • 꼭 필요하지만 자손마다 다르게 구현될 것으로 예상되는 경우 사용
  • 추상클래스를 상속받는 자손클래스에서 추상메서드의 구현부를 완성해야함
abstract class Player {
    int currentPos;     // 현재 Play되고 있는 위치를 저장하기 위한 변수
    
    Player() {
        currentPos = 0;
    }
    
    abstract void play(int Pos);    // 추상 메서드
    abstract void stop();
    
    void paly() {
        play(currentPos);           // 추상메서드 사용
    }
}

메서드를 이와 같이 미완성 상태로 남겨 놓은 이유는 메서드의 내용이 상속받은 클래스에 따라 달라질 수 있기 때문에 조상 클래스에서는 선언부만을 작성하고, 주석을 덕붙여 어떤 기능을 수행할 목적으로 작성되었는지 알려주고, 실제 내용은 상속받는 클래스에서 구현하도록 비워 두는 것이다.

예제

abstract class Pokemon {    		// 포켓몬
    String name;
	String Characteristic;
    
    abstract void skill1();
    abstract void skill2();
    abstract void skill3();
    abstract void skill4();
}

class Pikachu extends Pokemon {		// 피카츄
    @Override
    void skill1() {
        System.out.println("10만볼트");
    }

    @Override
    void skill2() {
        System.out.println("번개");
    }

    @Override
    void skill3() {
        System.out.println("볼트태클");
    }

    @Override
    void skill4() {
        System.out.println("전광석화");
    }
}

class Eevee extends Pokemon {		// 이브이
    @Override
    void skill1() {
        System.out.println("꼬리흔들기");
    }

    @Override
    void skill2() {
        System.out.println("울음소리");
    }

    @Override
    void skill3() {
        System.out.println("몸통박치기");
    }

    @Override
    void skill4() {
        System.out.println("애교부리기");
    }
}

interface

  • 일종의 추상클래스이다. 추상클래스보다 추상화 정도가 높다.
  • 추상클래스가 미완성 설계도면, interface는 그냥 껍데기 이다
  • 추상메서드와 상수(final)만을 멤버로 가질 수 있다.
  • 인스턴스를 생성할 수 없고, 클래스 작성에 도움을 줄 목적으로 사용된다.
  • 미리 정해진 규칙에 맞게 구현하도록 표준을 제시
interface InterName {
    public static final 상수변수 = value;
    public abstract 메서드이름(매개변수 목록);
}
  • 모든 멤버변수는 public static final 이어야 하며, 이를 생략 가능
  • 모든 메서드는 public abstract 이어야 하며, 이를 생략 가능
    • 단, static메서드와 디폴트 메서드는 예외(JDK 1.8부터)

인터페이스 상속

  • 인터페이스는 인터페이스만 상속 가능
  • 클래스와 달리 다중상속 가능
  • 조상 인터페이스의 모든 멤버를 상속
interface Movable {
    // 지정한 위치로 이동하는 기능의 메서드
    void move(int x, int y);
}

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

interface Fightable extends Movable, Attackable { }

인터페이스 구현
인터페이스를 상속할 때 일반 클래스나 추상 클래스는 확장한다는 의미의 'extends'를 사용하지만 인터페이스는 구현한다는 의미의 'implements'를 사용한다.

class Fighter implements Fightable {
    public void move(int x, int y) { code... }
    public void attack(Unit u) { code... }
}

만약 구현하는 인터페이스의 메서드 중 일부만 구현한 다면, abstract를 붙여서 추상클래스로 선언해야 한다.

그리고 다음과 같이 상속과 구현을 동시에 할 수도 있다.

class Fighter extends Unit implements Fightalbe {
	public void move(int x, int y) { code... }
    public void attack(Unit u) { code... }
}

인터페이스의 장점

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

좋은 웹페이지 즐겨찾기