Cloud SA's This and That

[JAVA] 상속과 인터페이스 + ChatGPT 활용하기 본문

Develop/JAVA

[JAVA] 상속과 인터페이스 + ChatGPT 활용하기

뽀삐누냐 2024. 1. 5. 14:57
SMALL

chatGPT를 통해 상속과 인터페이스를 사용한 자바 코드 학습을 진행해보았다.

 

<학습 키워드 정리>

[상속] : 자식 클래스가 부모의 속성을 물려받는 것.

 > 상속의 장점 : 클래스 확장이 용이하며 코드의 재사용이 가능하다.

 > 사용 키워드 : extends - 상속 관계 / super - 부모 클래스 생성자 호출

    -> 부모의 디폴트 생성자의 경우 자식 클래스의 생성자 호출 시 자동 호출된다

    -> 다만 부모 클래스에 디폴트 생성자가 없고 매개변수를 받는 생성자만 있다면 명시적으로 super()을 사용하여 호출해줘야 함.

 > 메소드 오버라이딩 : 부모 메소드를 자식 클래스에서 재정의

 > 자식 객체 생성 시 주의점 : 부모 클래스의 영역을 먼저 만들어야 한다.

 

[인터페이스] : 역할을 정의하는 하나의 타입으로 Prototype 메소드를 갖는다.(Prototype : 내용이 없는 메소드)

 > 인터페이스 장점 : 다형성 (한 객체를 다양하게 해석) / 그룹화 (여러 객체를 한 타입으로 관리)

 > 사용 키워드 : interface

 > 인터페이스는 클래스 정의와 유사한 형식을 가지며 인터페이스에서 선언된 메소드는 해당 인터페이스를 구현하는 클래스에서 반드시 메소드 오버라이딩되어야 한다. 

 

[추상클래스] : 객체 생성이 불가한 클래스로 자식 클래스를 통해 간접적으로 객체를 생성할 수 있다.

 > 사용 키워드 : abstract

 > 언제 사용? : 객체가 스스로 존재할 수 없는(하면 안되는) 경우에 사용한다.

 > 추상클래스 장점 : 코드 중복 제거 / 다형성 및 그룹화

 

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

 

<상속과 인터페이스를 사용한 코드> - 해당 코드로 ChatGPT를 통해 학습을 진행해 보았다. 

코드 출처 : 홍팍 (https://www.youtube.com/watch?v=Wuyr_X7CKCU&list=PLyebPLlVYXCjs-KSw3HF2jFX9-7S8HjlJ&index=36)

 

설명 : 기사(Knight)는 탱커(Tanker)의 역할을 수행하며 기사(Knight)는 성기사(HolyKnight)와 마검사(MagicKnight)로 2차 전직이 가능하다. 성기사(HolyKnight)의 경우 힐러(Healer)의 역할을, 마검사(MagicKnight)의 경우 마법사(Socerer)의 역할을 추가로 부여 받는다.

public class Main {
    public static void main(String[] args) {
        Knight uther = new HolyKnight("우서",200,10); 
        Knight arthas = new MagicKnight("아서스",150,20); 

        uther.increaseArmor();
        uther.increaseHp();

        HolyKnight holyUther = (HolyKnight) uther; 
        holyUther.healingAura(); 
        holyUther.holyArmor(); 
        
        arthas.increaseHp();
        arthas.increaseArmor();
        
        MagicKnight magicArthas = (MagicKnight) arthas;
        magicArthas.fireArmor();
        magicArthas.thunderBlade();
    }
}

interface Tanker{ // 탱커 역할을 인터페이스로 정의
    public void increaseArmor(); // Prototype 메소드
    public void increaseHp(); // Prototype 메소드
}

interface Healer{ // 힐러 역할을 인터페이스로 정의
    public void healingAura(); // Prototype 메소드
    public void holyArmor(); // Prototype 메소드
}

interface Sorcerer{ // 마법사 역할을 인터페이스로 정의
    public void fireArmor(); // Prototype 메소드
    public void thunderBlade(); // Prototype 메소드
}

class Knight implements Tanker{ // 탱커 역할을 부여받은 Knight 클래스
    protected String name;
    protected int hp;
    protected int armor;
    public Knight(String name, int hp, int armor){ // 생성자
        this.name = name;
        this.hp = hp;
        this.armor = armor;
    }
    public void increaseArmor(){ // 메소드 오버라이딩
        System.out.printf("[%s] increaseArmor() 시전!\n", name);
        System.out.println("\t아머가 +5 증가합니다.");
        armor += 5;
    }
    public void increaseHp(){ // 메소드 오버라이딩
        System.out.printf("[%s] increaseHp() 시전!\n", name);
        System.out.println("\t체력이 +100 증가합니다");
        hp += 100;
    }
}
class HolyKnight extends Knight implements Healer{ // Knight 클래스를 상속받은 힐러 역할을 부여받은 HolyKnight 클래스
    public HolyKnight(String name, int hp, int armor){
        super(name,hp,armor); // 부모 클래스 생성자 호출
    }
    public void healingAura(){ // 메소드 오버라이딩
        System.out.printf("[%s] healingAura() 시전!\n", name);
        System.out.println("\t초당 체력회복이 +10 증가합니다.");
    }
    public void holyArmor(){ // 메소드 오버라이딩
        System.out.printf("[%s] holyArmor() 시전!\n", name);
        System.out.println("\t데미지를 -10 덜 받습니다.");
    }
}
class MagicKnight extends Knight implements Sorcerer{ // Knight 클래스를 상속받은 마법사 역할을 부여받은 HolyKnight 클래스
    public MagicKnight(String name, int hp, int armor){
        super(name, hp, armor); // 부모 클래스 생성자 호출
    }
    public void fireArmor(){ // 메소드 오버라이딩
        System.out.printf("[%s] fireArmor() 시전!\n", name);
        System.out.println("\t주변 적에게 초당 +10의 데미지를 줍니다.");
    }
    public void thunderBlade(){ // 메소드 오버라이딩 
        System.out.printf("[%s] thunderBlade() 시전!\n", name);
        System.out.println("\t매 공격시 +10의 추가 데미지를 줍니다.");
    }
}

 

<출력결과>

 

<메인 클래스>

public static void main(String[] args) {
        Knight uther = new HolyKnight("우서",200,10); 
        Knight arthas = new MagicKnight("아서스",150,20); 

        uther.increaseArmor();
        uther.increaseHp();

        HolyKnight holyUther = (HolyKnight) uther; 
        holyUther.healingAura(); 
        holyUther.holyArmor(); 
        arthas.increaseHp();
        arthas.increaseArmor();

        MagicKnight magicArthas = (MagicKnight) arthas;
        magicArthas.fireArmor();
        magicArthas.thunderBlade();
    }
}

 

 > 여기서 아직 학습이 부족한 나로써는 메인 클래스 부분에 대해 더 정확히 분석하고 싶어 ChatGPT를 사용해보았다.

 

 > 우선 질문할 주제에 알려준 뒤 위의 코드를 올리고 질문을 던져보았다.

 

 

 > 해당 답변을 통해 메인 클래스의 메인 메소드에서 Knight 타입의 uther 변수가 HolyKnight 객체를 참조한다는 것과 실제 선언된 타입은 Knight이기 때문에 형변환을 통해 HolyKnight로써 사용(HolyKnight 클래스 메소드 사용)할 수 있다는 것을 알게되었다.

그렇다면 왜 이렇게 객체를 참조를 하는지에 대해 궁금했고 이어서 질문을 던져보았다.

 

 > 정리하자면 Knight 타입으로 선언하여 HolyKnight 객체를 참조하는 것은 코드의 유연성과 확장성, 다형성 등을 최대한 활용하기 위함이라고 한다. 그리고 ChatGPT 사용 전 Custom 설정 부분이 있는데 그 설정 부분에 답을 어떤식으로 해달라고 적은 적이 있다. (예를 들어 모르겠다라는 답은 하지말라던가, 나에게 추가 질문을 해달라던가..) 이 덕분인지 ChatGPT는 나에게 3가지의 질문을 던졌다.

 

 

 > 나의 현재 학습에 매우 도움이 될 것 같아 해당 질문에 대한 답을 해달라고 하였고 ChatGPT는 각 질문에 대해 답해주었다.

> 확실히 답변을 보면 현재 내가 알고자하는 것에 대해 정확히 파악하고 나를 더 성장시켜줄 수 있도록 질문을 던지는 것이 보였다..(너무 신기..) 

그리고 추가적으로 대화를 이어가다 다형성에 대해 좀 더 학습하고자 해당 질문을 던졌다. (형변환은 가독성을 떨어뜨린다기에 질문에 추가하였다.)

 

 

> 다형성을 통해 코드를 구성하기 위해서는 공통된 인터페이스나 부모 클래스를 통해 작업하는 방식을 채택하는 것을 권하며 예제를 보여준다. 위의 대화들을 통해 메인메소드를 수정하여 주석처리를 한 뒤 ChatGPT에 확인요청을 하였다.

(수정한 메인클래스 코드) - 3문단 모두 같은 출력 결과이다

 public static void main(String[] args) {
        Knight uther = new HolyKnight("우서",200,10); //knight 타입의 uther 변수가 HolyKnight 객체 참조
       
        HolyKnight holyUther = (HolyKnight) uther; // 형변환 (Knight -> HolyKnight)
        holyUther.healingAura(); // HolyKnight 클래스의 메소드 호출
        holyUther.holyArmor(); // HolyKnight 클래스의 메소드 호출

        Healer healerUther = (Healer) uther; // 형변환 (Knight -> Healer) <다형성에 최적화>
        healerUther.healingAura(); // Healer 인터페이스의 메소드 호출
        healerUther.holyArmor(); // Healer 인터페이스의 메소드 호출

        ((Healer)uther).healingAura(); // 같은 결과 (코드 가독성에는 별로)
        ((Healer)uther).holyArmor();
        }
}

 

 

> 솔직히 해당 내용들을 독학으로 책이나 인터넷 서칭을 통해 알아내려 했다면 이미 지쳐서 예전의 과오를 되풀이하고있지 않았을까싶다..ㅎㅎ 물론 아직 갈날이 멀었지만 ChatGPT 덕분에 좀 더 빠르고 효율적으로 학습이 가능한 것은 틀림이 없다! 

Spring Boot 가쟈!

LIST