본문 바로가기

Java/StudyNote

JAVA_07-3 #객체지향 프로그래밍 #다형성 #추상클래스

다형성(Polymorphism)

 

객체지향 프로그래밍의 특징

하나의 객체가 여러개의 자료형 타입을 가질 수 있는 것

다형성을 이용하면 복잡한 형태의 분기문을 간단하게 처리할 수 있는 경우가 많다.

 

interface Predator{
    String getFood();
    default void printFood(){
        System.out.printf("my food is %s\n", getFood());
    }

    // 인터페이스 상수
    int LEG_COUNT = 4;

    // 인터페이스 스테틱 메서드
    static int speed(){
        return LEG_COUNT * 30;
    }

}

// 인터페이스 Barkable
interface Barkable{
    void bark();
}


class Animal_0507{
    String name;
    void setName(String name){
        this.name = name;
    }
}

// Tiger, Lion 클래스에 인터페이스 구현(Implements), 여러개의 인터페이스를 가질 수 있다.
class Tiger extends Animal_0507 implements Predator, Barkable{
    // 인터페이스의 메소드는 항상 public 으로 구현
    public String getFood(){
        return "apple";
    }
    public void bark() {
        System.out.println("어흥");
    }
}

class Lion extends Animal_0507 implements Predator, Barkable{
    public String getFood(){
        return "banana";
    }
    public void bark() {
        System.out.println("으르렁");
    }
}

class ZooKeeper{
    // 인터페이스 Predator 입력으로 대체
    void feed(Predator predator){
        System.out.println("feed " + predator.getFood());
        // 디폴트 메서드 출력
        predator.printFood();
        // 인터페이스 스태틱 메서드 출력
        System.out.println(Predator.speed());
    }
}

class Bouncer {
    // barkAnimal 메소드는 입력으로 받은 animal 객체에 따라 다른 내용을 출력
    void barkAnimal(Barkable animal){
        animal.bark();
    }
}

public class Sample_0507 {
    public static void main(String[] args){
        ZooKeeper zooKeeper = new ZooKeeper();
        Tiger tiger = new Tiger();
        Lion lion = new Lion();
        zooKeeper.feed(tiger);  // apple 출력
        zooKeeper.feed(lion);   // banana 출력

        Bouncer bouncer = new Bouncer();
        bouncer.barkAnimal(tiger);  // 어흥 출력
        bouncer.barkAnimal(lion);   // 으르렁 출력
    }
}

 

위의 Tiger 클래스 객체는 다음과 같은 여러가지 자료형으로 표현할 수 있다.

 

Tiger tiger = new Tiger();  // Tiger is a Tiger
Animal animal = new Tiger();  // Tiger is a Animal
Predator predator = new Tiger();  // Tiger is a Predator
Barkable barkable = new Tiger();  // Tiger is a Barkable

 

* predator 객체는 getFood() 메소드가 선언된 Predator 인터페이스의 객체이므로 getFood 메소드만 호출 가능

* Barkable 로 선언된 barkable 객체는 bark 메소드만 호출이 가능

 

getFood 메소드와 bark 메소드를 하나의 객체에서 모두 사용하고 싶다면?

- 인터페이스는 일반 클래스와 달리 extends를 사용해 여러개의 인터페이스를 동시에 상속할 수 있다.(다중상속)

* 일반 클래스는 단일상속만 가능

 

interface Predator{
    String getFood();
    default void printFood(){
        System.out.printf("my food is %s\n", getFood());
    }

    // 인터페이스 상수
    int LEG_COUNT = 4;

    // 인터페이스 스테틱 메서드
    static int speed(){
        return LEG_COUNT * 30;
    }

}

// 인터페이스 Barkable
interface Barkable{
    void bark();
}

// 다중 상속 인터페이스
interface BarkablePredator extends Predator, Barkable{

}


class Animal_0507{
    String name;
    void setName(String name){
        this.name = name;
    }
}

// Tiger, Lion 클래스에 인터페이스 구현(Implements), 여러개의 인터페이스를 가질 수 있다.
class Tiger extends Animal_0507 implements Predator, Barkable{
    // 인터페이스의 메소드는 항상 public 으로 구현
    public String getFood(){
        return "apple";
    }
    public void bark() {
        System.out.println("어흥");
    }
}

// Predator, Barkable을 다중상속한 BarkablePredator 인터페이스 구현
class Lion extends Animal_0507 implements BarkablePredator{
    public String getFood(){
        return "banana";
    }
    public void bark() {
        System.out.println("으르렁");
    }
}

class ZooKeeper{
    // 인터페이스 Predator 입력으로 대체
    void feed(Predator predator){
        System.out.println("feed " + predator.getFood());
    }
}

class Bouncer {
    // barkAnimal 메소드는 입력으로 받은 animal 객체에 따라 다른 내용을 출력
    void barkAnimal(Barkable animal){
        animal.bark();
    }
}

public class Sample_0507 {
    public static void main(String[] args){
        Tiger tiger = new Tiger();
        Lion lion = new Lion();

        Bouncer bouncer = new Bouncer();
        bouncer.barkAnimal(tiger);  // 어흥 출력
        bouncer.barkAnimal(lion);   // 으르렁 출력
    }
}

 

 


추상클래스(Abstract Class)

 

추상클래스는 인터페이스의 역할도 하면서 클래스의 기능도 가진다.

추상클래스의 상수는 static 선언이 필요하다.

추상클래스를 만들기 위해서는 class 앞에 abstract 라고 표기해야 한다.

인터페이스의 메소드와 같은 역할을 하는 메소드에도 abstract를 붙여야 한다.

* 추상클래스는 일반클래스와 달리 단독으로 객체를 생성할 수 없다. 반드시 추상클래스를 상혹한 실제 클래스를 통해서만 객체를 생성할 수 있다.

 

// 인터페이스를 추상클래스로 변경
abstract class Predator extends Animal_0507{
    abstract String getFood(); // 추상클래스의 메소드에도 abstract 이 붙어야 한다.
    void printFood(){          // 인터페이스가 아니므로 default 가 붙을 수 없다.
        System.out.printf("my food is %s\n", getFood());
    }

    // 추상클래스 상수
    static int LEG_COUNT = 4;          // 추상클래스의 상수는 static 선언이 필요하다.

    // 인터페이스 스테틱 메서드
    static int speed(){
        return LEG_COUNT * 30;
    }

}

// 인터페이스 Barkable
interface Barkable{
    void bark();
}


class Animal_0507{
    String name;
    void setName(String name){
        this.name = name;
    }
}

// Tiger, Lion 클래스는 추상클래스를 상속하도록 변경
class Tiger extends Predator implements Barkable{
    // 인터페이스의 메소드는 항상 public 으로 구현
    public String getFood(){
        return "apple";
    }
    public void bark() {
        System.out.println("어흥");
    }
}

class Lion extends Predator implements Barkable{
    public String getFood(){
        return "banana";
    }
    public void bark() {
        System.out.println("으르렁");
    }
}

class ZooKeeper{
    // 인터페이스 Predator 입력으로 대체
    void feed(Predator predator){
        System.out.println("feed " + predator.getFood());
    }
}

class Bouncer {
    void barkAnimal(Barkable animal){
        animal.bark();
    }
}

public class Sample_0507 {
    public static void main(String[] args){
        Tiger tiger = new Tiger();
        Lion lion = new Lion();

        Bouncer bouncer = new Bouncer();
        bouncer.barkAnimal(tiger);  // 어흥 출력
        bouncer.barkAnimal(lion);   // 으르렁 출력
    }
}

 

 


참고
https://wikidocs.net/book/31

 

점프 투 자바

**초보 프로그래머를 위한 자바 입문서** 이 책은 문법위주의 지식보다는 이해중심의 지식을 전달하는 것을 주 목적으로 한다. 예를 들어 자바에서 잘 파악하기 힘든 개념 ...

wikidocs.net

 

반응형