abstract

현서·2025년 5월 22일
1

자바

목록 보기
12/32
post-thumbnail

1. abstract

abstract: 자바에서 추상 클래스나 추상 메서드를 정의할 때 사용한다.

추상 클래스 : 객체를 직접 생성할 수 없고, 공통적인 속성과 동작을 정의하여 상속을 통해 구체화되도록 설계된 클래스이다.

추상 메서드 : 자식 클래스에서 반드시 오버라이딩(재정의)해야 한다.
-> 객체지향 프로그래밍에서 다형성과 설계 유연성을 높일 수 있다.

1. 추상 클래스 (abstract class)

  • abstract 키워드를 클래스 앞에 붙이면 추상 클래스가 된다.
  • 인스턴스를 만들 수 없다. (new로 생성 불가)
  • 일반 메서드와 추상 메서드(몸체 없는 메서드)를 모두 가질 수 있다.
  • 상속을 통해 자식 클래스에서 구체적으로 구현하도록 강제할 수 있다.
package lesson05;

abstract class Ex01_Animal {
    String name;

    public Ex01_Animal(String name){
        this.name = name;
    }

    abstract void sound();

    void sleep(){
        System.out.println(name + "이(가) 잠을 잡니다.");
    }
}

class Dog extends Ex01_Animal {
    public Dog(String name){
        super(name);
    }

    @Override
    void sound() {
        System.out.println(name + "이(가) 멍멍 짖습니다.");
    }

    void eat(){
        System.out.println(name +"이(가) 먹습니다.");
    }
}

public class Ex01_Main {
    public static void main(String[] args) {
      //  Animal animal = new animal("동물"); // ❌ 추상 클래스는 객체 생성 불가
        Dog dog = new Dog("루시");
        dog.sound();
        dog.sleep();
        dog.eat();

        Ex01_Animal dog2 = new Dog("루시");
        dog2.sound();
        dog2.sleep();
//        dog2.eat();
    }
}
루시이(가) 멍멍 짖습니다.
루시이(가) 잠을 잡니다.
루시이(가) 먹습니다.
루시이(가) 멍멍 짖습니다.
루시이(가) 잠을 잡니다.

2. 추상 메서드 (abstract method)

  • 메서드의 선언만 하고, 본문(중괄호 {}) 없이 끝나는 메서드이다.
  • 반드시 추상 클래스 안에서만 정의할 수 있다.
  • 자식 클래스는 이 메서드를 반드시 오버라이딩(재정의) 해야 한다.
package lesson05;

abstract class Shape{
    abstract double getArea(); // 추상 메서드: 면적 계산
}

class Circle extends Shape{
    double radius;
    Circle(double radius){
        this.radius = radius;
    }

    @Override
    double getArea() {
        return radius * radius * Math.PI;
    }
}

class Rectangle extends Shape{
    double width, height;
    Rectangle(double width, double height){
        this.width = width;
        this.height = height;
    }

    @Override
    double getArea() {
        return width * height;
    }
}

public class Ex02_Main {
    public static void main(String[] args) {
        Shape s1 = new Circle(5);
        System.out.println("원 면적: " + s1.getArea());
        Shape s2 = new Rectangle(4, 5);
        System.out.println("사각형 면적: " + s2.getArea());
    }
}
원 면적: 78.53981633974483
사각형 면적: 20.0

주의사항

  • 추상 클래스 내에는 일반 메서드, 필드, 생성자도 정의할 수 있다.
  • 추상 클래스를 상속한 클래스는 모든 추상 메서드를 구현해야 한다.
    (구현하지 않는 경우, 그 클래스도 추상 클래스로 선언해야 한다.)
  • 인터페이스와는 달리 생성자, 상태(필드)를 가질 수 있다.

2. 포켓동물 게임 만들기

import java.util.Random;
import java.util.Scanner;

abstract class Animal {
    String name;
    int maxHp;
    int hp;
    int power;
    int maxSkillCount;
    int skillCount;

    public Animal(String name, int power, int maxHp, int maxSkillCount) {
        this.name = name;
        this.power = power;
        this.maxHp = maxHp;
        this.hp = maxHp;
        this.maxSkillCount = maxSkillCount;
        this.skillCount = maxSkillCount;
    }

    abstract void attack();
    abstract int getAttackPower();
    abstract String getSkillName();
    abstract void useSkill(Animal enemy);

    boolean isAlive() {
        return hp > 0;
    }

    boolean canUseSkill() {
        return skillCount > 0;
    }

    void takeDamage(int damage) {
        hp -= damage;
        if (hp < 0) hp = 0;
    }

    void printStatus() {
        System.out.println(name + " 체력: " + hp + "/" + maxHp + " | 스킬 남은 횟수: " + skillCount + "/" + maxSkillCount);
    }
}

class Dragon extends Animal {
    public Dragon() {
        super("드래곤", 30, 180, 3); // 체력 상향, 스킬 3회
    }

    @Override
    void attack() {
        System.out.println("🔥 드래곤이 불을 내뿜는다!");
    }

    @Override
    int getAttackPower() {
        return power + new Random().nextInt(20); // 30~49
    }

    @Override
    String getSkillName() {
        return "파이어 브레스";
    }

    @Override
    void useSkill(Animal enemy) {
        if (canUseSkill()) {
            skillCount--;
            int damage = 40 + new Random().nextInt(20); // 40~59
            System.out.println("🔥 드래곤의 스킬! 파이어 브레스!! (불꽃 데미지 " + damage + ")");
            enemy.takeDamage(damage);
        } else {
            System.out.println("❌ 드래곤은 더 이상 스킬을 사용할 수 없습니다!");
        }
    }
}

class Wolf extends Animal {
    public Wolf() {
        super("늑대", 25, 160, 2); // 체력 상향, 스킬 2회
    }

    @Override
    void attack() {
        System.out.println("🌕 늑대가 어둠 속에서 덮친다!");
    }

    @Override
    int getAttackPower() {
        return power + new Random().nextInt(15); // 25~39
    }

    @Override
    String getSkillName() {
        return "달빛 송곳니";
    }

    @Override
    void useSkill(Animal enemy) {
        if (canUseSkill()) {
            skillCount--;
            int damage = 35 + new Random().nextInt(15); // 35~49
            System.out.println("🌙 늑대의 스킬! 달빛 송곳니!! (강력 데미지 " + damage + ")");
            enemy.takeDamage(damage);
        } else {
            System.out.println("❌ 늑대는 더 이상 스킬을 사용할 수 없습니다!");
        }
    }
}

class Bear extends Animal {
    public Bear() {
        super("곰", 20, 200, 1);
    }

    @Override
    void attack() {
        System.out.println("🐻 곰이 앞발로 내려친다!");
    }

    @Override
    int getAttackPower() {
        return power + new Random().nextInt(10); // 20~29
    }

    @Override
    String getSkillName() {
        return "대지 강타";
    }

    @Override
    void useSkill(Animal enemy) {
        if (canUseSkill()) {
            skillCount--;
            int damage = (int)(enemy.hp * 0.3);
            if (damage < 25) damage = 25;
            System.out.println("🌍 곰의 스킬! 대지 강타!! (적 체력의 30% 데미지: " + damage + ")");
            enemy.takeDamage(damage);
        } else {
            System.out.println("❌ 곰은 더 이상 스킬을 사용할 수 없습니다!");
        }
    }
}

// === 메인 게임 ===

public class AnimalBattleGame {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        Animal[] allAnimals = { new Dragon(), new Wolf(), new Bear() };
        Animal[] playerTeam = new Animal[2];
        Animal[] enemyTeam = new Animal[2];
        Random rand = new Random();

        System.out.println("🧙 전설의 포켓동물 배틀에 오신 걸 환영합니다!");
        System.out.println("두 마리의 포켓동물을 선택하세요:");

        for (int i = 0; i < 2; i++) {
            System.out.println("1. 드래곤 🐉\n2. 늑대 🐺\n3. 곰 🐻");
            System.out.print((i + 1) + "번째 동물 선택: ");
            int choice = sc.nextInt();
            playerTeam[i] = copyAnimal(allAnimals[choice - 1]);
        }

        // 적 팀 랜덤 구성
        for (int i = 0; i < 2; i++) {
            while (true) {
                Animal enemy = copyAnimal(allAnimals[rand.nextInt(3)]);
                boolean exists = false;
                for (int j = 0; j < i; j++) {
                    if (enemy.name.equals(enemyTeam[j].name)) {
                        exists = true;
                        break;
                    }
                }
                if (!exists) {
                    enemyTeam[i] = enemy;
                    break;
                }
            }
        }

        int playerIdx = 0;
        int enemyIdx = 0;

        while (true) {
            Animal player = playerTeam[playerIdx];
            Animal enemy = enemyTeam[enemyIdx];

            System.out.println("\n====================================");
            System.out.println("👊 현재 전투 중인 포켓동물");
            player.printStatus();
            enemy.printStatus();

            // 플레이어 턴
            System.out.println("\n[당신의 턴]");
            System.out.println("1. 일반 공격");
            System.out.println("2. 스킬 사용 (" + player.getSkillName() + ")");
            System.out.println("3. 동물 교체");
            System.out.print("선택 >> ");
            int action = sc.nextInt();

            if (action == 1) {
                player.attack();
                int damage = player.getAttackPower();
                System.out.println("💥 공격력: " + damage);
                enemy.takeDamage(damage);
            } else if (action == 2) {
                player.useSkill(enemy);
            } else if (action == 3) {
                int otherIdx = 1 - playerIdx;
                if (!playerTeam[otherIdx].isAlive()) {
                    System.out.println("⚠️ 다른 동물이 전투불능입니다!");
                    continue;
                }
                playerIdx = otherIdx;
                System.out.println("🔁 포켓동물 교체!");
                continue;
            }

            if (!enemy.isAlive()) {
                System.out.println("✅ 적 " + enemy.name + "이(가) 쓰러졌습니다!");
                enemyIdx++;
                if (enemyIdx >= 2) {
                    System.out.println("🎉 당신이 승리했습니다!!");
                    break;
                }
            }

            // 적 턴
            Animal currEnemy = enemyTeam[enemyIdx];
            Animal currPlayer = playerTeam[playerIdx];
            System.out.println("\n[👾 적의 턴: " + currEnemy.name + "]");

            int enemyChoice;
            if (currEnemy.hp < 60 && currEnemy.canUseSkill() && rand.nextInt(100) < 70) {
                enemyChoice = 1;
            } else {
                enemyChoice = 0;
            }

            if (enemyChoice == 0) {
                System.out.println("👾 적이 일반 공격을 선택합니다!");
                currEnemy.attack();
                int damage = currEnemy.getAttackPower();
                System.out.println("💥 공격력: " + damage);
                currPlayer.takeDamage(damage);
            } else {
                System.out.println("👾 적이 스킬 '" + currEnemy.getSkillName() + "'을(를) 사용합니다!");
                currEnemy.useSkill(currPlayer);
            }

            if (!currPlayer.isAlive()) {
                System.out.println("☠️ 당신의 " + currPlayer.name + "이(가) 쓰러졌습니다!");
                if (!playerTeam[1 - playerIdx].isAlive()) {
                    System.out.println("💀 모든 포켓동물이 쓰러졌습니다. 패배...");
                    break;
                } else {
                    playerIdx = 1 - playerIdx;
                    System.out.println("🔁 자동으로 다른 포켓동물로 교체합니다!");
                }
            }
        }

        sc.close();
    }

    public static Animal copyAnimal(Animal original) {
        if (original.name.equals("드래곤")) return new Dragon();
        else if (original.name.equals("늑대")) return new Wolf();
        else return new Bear();
    }
}
profile
The light shines in the darkness.

0개의 댓글