IT_Programming/Java

추상 클래스와 인터페이스

JJun ™ 2007. 6. 29. 19:27
LONG
/*
   추상 클래스와 인터페이스 비교하기

   - 추상 클래스
      : 추상 클래스는 미완성 클래스이다. 객체가 가지는 특성을 추상화했으나 구현하지 못한 것이다.
        추상 클래스를 상속한 자식 클래스는 구현하지 못한 메서드를 구현해야만 객체를 생성할 수 있다.
        추상 메서드는 "프로토 타입 메서드"라고도 한다.
      [특징]
       - 선언과 구현을 분리시킨다.
       - 부모는 자식보다 추상적 또는 일반적이다.
       - 자식의 특징에 알맞은 구체적 메서드를 자식의 클래스에서 오버라이딩한다.
       1) 추상 메서드가 1개 이상 있을 때(abstract field는 없다.)
       2) 추상 클래스를 상속하거나, 인터페이스를 구현한다고 했는데, 오버라이딩 하지 않거나
           구현 안 한 메서드가 있을 때
       3) 추상 메서드는 없지만 반드시 상속을 해서 사용하도록 강제성을 두기 위해
           (final과 반대 - final class는 상속을 금지시켜서 자식이 없다.)

    - 인터페이스
       : 인터페이스는 프로토 타입이라고 불리는 구현되지 못한 메서드(추상 메서드)만 선언한다.
         모든 메서드가 추상 메서드인 추상 클래스는 인터페이스로 바꿀 수 있다.
         추상 메서드를 선언 할 깨 abstract 키워드를 메서드에 붙인다. 인터페이스에서 선언된 변수는
         자동으로 final static이 붙어 상수가 되고, 메서드는 자동으로 abstract 키워드가 붙는다.
       [특징]
       - 선언과 구현을 분리시킨다.
       - 커플링을 떨어뜨린다.
       - 다중 상속을 흉내낸다.
       1) 변수는 자동으로 상수가 된다.
       2) private은 사용하지 말고 default 이상을 사용하라.
           (void show() → public void show()가 된다.)
       3) {}(바디)를 붙이지 않는다.
       4) 인터페이스에 선언되어 메서드를 구현 못하면 자식 클래스는 추상 클래스가 된다.
       5) 인터페이스가 여러 개일 때 ,(컴마)를 사용한다.
       6) 상속이 우선이다.
       7) 인터페이스는 여러 개의 인터페이스를 extends 할 수 있다.
*/
interface Ship // 인터페이스 선언
{
 int move();
// 사람은 몇 명 나르는가? (자동으로 public abstract int move();가 된다.)
 int carry();
// 무기를 몇 정 나르는가? (자동으로 public abstract int carry();가 된다.)
}
abstract class Plane // 추상 클래스 선언
{
 public abstract void fly();
// 추상 메서드
 public abstract int power();
// 추상 메서드
 // 추상 메서드 때문에 추상 클래스가 된다.
}
class SeaAirplane extends Plane implements Ship // 클래스와 인터페이스를 이용한 다중 상속
{
 private String id="Air Balls";
 public SeaAirplane()
 {
// 멤버필드를 초기화 하려고 아규먼트가 하나 있는 생성자를 호출하면서 "LeeMass"를 대입
  this("LeeMass");
// this 생성자를 이용하여 멤버필드 초기화
 }
 public SeaAirplane(String id)
 {
  this.id=id;
 } // 추상화
 public void fly()
 {
  System.out.println("엔진과 날개를 이용하여 날아감");
 }
 public int power()
 {
  return 10000;
 }// 인터페이스
 public int move()
 {
  return 5;
 }// 사람을 몇 명 나르는가?
 public int carry()
 {
  return 300;
 }// 무기를 몇 정 나르는가?
 public String toString()
 {
  return this.id+"가 "+power()+"마력으로 "+move()+"명을 나른다.";
 }
}
class SeaAirplaneUtil // static 메서드를 선언하는 클래스로 show를 오버로딩한다.
{
/* show(Plane p), show(Ship s),  show(SeaAirplane s)와 같이 각 타입에 맞게 호출 할 수 있다.
       그러나 show(Plane p), show(Ship s)와 같이 오버로딩된 메서드 두 개만  있을 경우,
       show 메서드의 아규먼트로 SeaAirplane 타입을 입력하면 reference to show is ambibuous라는
       에러가 난다. SeaAirplane은 Plane도 되고, Ship도 될 수 있기 때문이다. */
 public static void show(Plane p)
 {
  System.out.print(p.power());
  p.fly();
 }
 public static void show(Ship s)
 {
  System.out.print(s.move()+"명을 태우고 ");
  System.out.println(s.carry()+"정을 싣고 가고 있다.");
 }
 public static void show(SeaAirplane s)
 {
  System.out.println(s);
 }
 public static void showOnly(Ship s) // Ship과 SeaAirplane 타입을 아규먼트로 받을 수 있다.
 {
  System.out.print(s.move()+"명을 태우고 ");
  System.out.println(s.carry()+"정을 싣고 가고 있다.");
 }
 public static void showPlane(Plane p) // Plane과 SeaAirplane 타입을 아규먼트로 받을 수 있다.
 {
  System.out.print(p.power());
  p.fly();
 }
}
class SeaAirplaneMain
{
 public static void main(String[] args)
 {
  SeaAirplane sea = new SeaAirplane("CS110");
// SeaAirplane 타입으로 SeaAirplane의 객체를 생성
  Plane p = sea;
// 추상클래스 Plane의 이름으로 SeaAirplane을 받을 수 있는 아규먼트의 다형성
  Ship s = sea; // 추상클래스 Ship의 이름으로 SeaAirplane을 받을 수 있는 아규먼트의 다형성
  SeaAirplaneUtil.show(sea); // SeaAirplane을 아규먼트로 갖는 show를 호출한다.
  SeaAirplaneUtil.show(p);
// Plane을 아규먼트로 갖는 show를 호출한다.
  SeaAirplaneUtil.show(s); // Ship을 아규먼트로 갖는 show를 호출한다.
  SeaAirplaneUtil.showOnly(sea);
  SeaAirplaneUtil.showPlane(sea);
 }
}
ARTICLE

/*
      ======================================================================================
      추상 클래스

      1) abstract 키워드를 사용
      2) 추상 클래스는 자기 이름으로 자신의 객체를 생성할 수 없으며, 추상 클래스를 상속한

          자식 클래스의 객체를 생성하여 사용한다.
      3) 추상 메서드는 반드시 자식 클래스에서 오버라이딩하여 구현해야 한다.
          그렇지 않으면 자식도 추상 클래스가 된다.
      4) 추상 클래스는 반드시 자식을 가져야 한다.

      --------------------------------------------------------------------------------------

      [추상 클래스가 되는 3가지 경우]

   1) 추상 메서드가 1개 이상일 때
   2) 추상 클래스를 상속했지만 추상 메서드를 오버라이딩하지 않거나,
       인터페이스를 구현했지만 메서드를 구현하지 않았을 때
   3) 추상 메서드가 없는데 강제로 상속하여 사용하려는 경우

      ======================================================================================
*/

abstract class Ship
{
 public abstract int move();
// 사람을 몇 명 나르는가?
 public abstract int carry();
// 무기를 몇 정 나르는가?
}

class Boat extends Ship
{
 public int move()
 {
  return 6;
 }// 사람을 몇 명 나르는가?

 public int carry()
 {
  return 0;
 } // 무기를 몇 정 나르는가?

 public String name()
 {
  return "쌩쌩 보트: ";
 }
}

class Cruise extends Ship
{
 public int move()
 {
  return 300;
 }// 사람을 몇 명 나르는가?

 public int carry()
 {
  return 200;
 }
// 무기를 몇 정 나르는가?
 public String name()
 {
  return "전함 무궁화: ";
 }
}

class ShipUtil
{
 public static void search(Ship s)
 {
  System.out.println(s.move());
  System.out.println(s.carry());

  if(s instanceof Boat)
  {
   Boat b = (Boat)s;
   System.out.println("Boat 이름: "+b.name());
  }
  else if(s instanceof Cruise)
  {
   Cruise b = (Cruise)s;
   System.out.println("Cruise 이름: "+b.name());
  }
 }
}

public class ShipMain
{
 public static void main(String[] args)
 {
  Ship ship1 = new Boat();
  Ship ship2 = new Cruise();

  System.out.println(ship1.move());
  System.out.println(ship1.carry());
  System.out.println(ship2.move());
  System.out.println(ship2.carry());

  ShipUtil.search(ship2);
 }
}

 

===========================================================================================

 

/*
 =======================================================================================

 인터페이스(interface)

 (1) interface 키워드 사용.

 (2) 인터페이스 자기 이름으로 객체를 만들 수 없다.
      → 인터페이스 자기 이름으로 인터페이스를 구현한 클래스의 객체를 생성할 수 있다.

 (3) 인터페이스의 추상 메서드(선언된 메서드, 프로토 타입 메서드)는 반드시 인터페이스를
      구현하는 클래스에서 구현되어야 한다.

 (4) 인터페이스만 구현하고, 추상 메서드를 구현하지 않은 클래스는 추상 클래스가 된다.

 (5) 인터페이스는 선언과 구현을 분리시키며, 추상 메서드를 반드시 구현해야 하는 강제성이 있어
      인터페이스를 만든 의도대로 클래스를 구현할 수 있다.

 (6) 인터페이스의 추상 메서드는 구현된 것이 아니므로 커플링(다른 클래스에 대한 의존성)을 떨어뜨린다.

 (7) 다중 상속을 흉내낸다.

 ---------------------------------------------------------------------------------------

 [인터페이스(interface)의 특징]

 1) 변수는 자동으로 상수가 된다. (int a=1;은 public final static int a=1;이 된다.)
 2) private은 사용하지 말고 기본 접근 제한자 이상을 사용하자.
     void show();는 public abstract void show();가 된다. 그래서 추상 메서드라 불린다.
 3) void show();와 같이 바디({})를 붙이지 않는다. 메서드 이름을 나열한다.
 4) 인터페이스의 추상 메서드를 구현하지 못하면 자식 클래스는 추상 클래스가 된다.
 5) 인터페이스가 여러 개일 때,  ,(컴마)를 사용한다. (ex) Penguin implements IFish, IBird
 6) 상속이 우선이다. (ex) Penguin extends Animal implements IFish
 7) 인터페이스는 여러개의 인터페이스를 상속할 수 있다.
     (ex) IPenguin extends IAnimal, IFish, IBird

 =======================================================================================
*/
interface Flyer
{
 int fast = 100;
// 상수가 됨
 void fly();
 boolean isAnimal();
}

class Bird implements Flyer
{
 public void fly()
 {
  System.out.println("날개를 휘저으며 날아감");
 }

 public boolean isAnimal()
 {
  return true;
 }
}

class Airplane implements Flyer
{
 public void fly()
 {
  System.out.println("엔진과 날개를 이용하여 날아감");
 }

 public boolean isAnimal()
 {
   return false;
 }
}

class FlyerUtil
{
 public static void show(Flyer f)
 {
  f.fly();
  System.out.println(f.isAnimal());
 }
}

public class FlyerMain
{
 public static void main(String[] args)
 {
  System.out.println(Flyer.fast); // 상수

  Bird b = new Bird();
  FlyerUtil.show(b);

  Airplane ap = new Airplane();
  ap.fly();
  FlyerUtil.show(ap);

  Flyer f =new Bird();
  f.fly();

  System.out.println(f.isAnimal());
  FlyerUtil.show(f);

  Bird bf = (Bird)f;
  FlyerUtil.show(bf);
 }
}

ShipMain.java
0.0MB
FlyerMain.java
0.0MB
SeaAirplaneMain.java
0.0MB