본문 바로가기
스파르타(부트캠프)/TIL (Today I Learned)

[내일배움캠프] 스파르타 8일차_24.10.10

by Kimuky 2024. 10. 10.

공부 내용 및 활동 내용

 -  Java 기초 (클래스)

1. This, Super
2. Abstract (추상 클래스)
3. Interface
4. 클래스 설계해보기
5. 스파르타 종합반 3주차 숙제 재분석

 

아... 어렵다 자바.. 자바문법 종합반 2주차까지는 제어, 컬렉션이라 이해를 금방할 수 있었지만 클래스는 정말 쉽지 않았다.

그래도 포기하지 말자 ㅠㅠ

오늘 TIL은 자바 문법 클래스 중 잘 이해가 안 가는 부분 위주로 복습했다.


1. This, Super

- This는 객체 즉, 인스턴스 자신을 표현하는 키워드이다.

- SUPER는 부모클래스의 벰버를 참조할 수 있는 키워드이다.

-> 이것만 들어서는 잘 이해가 가지 않는다. 그래서 실제로 코드를 작성해보며 이해해보았다.

// Class A
public class A {
    A() {
        this(3);
        System.out.println("A 생성자입니다.");
    }

    A(int n) {
        System.out.println("A 생성자 "+ n);
    }
}

//Class B
public class B extends A {
    B() {
        this(45);
        System.out.println("B 생성자입니다.");
    }

    B(int a) {
        System.out.printf("B 생성자 2-%d입니다.\n", a);
    }
}

클래스를 이렇게해두고

//Main
public class Main {
    public static void main(String[] args) {
//        A aa = new A();
//        B bb = new B();
        B bb = new B();
    }

}

//출럭
A 생성자 3
A 생성자입니다.
B 생성자 2-45입니다.
B 생성자입니다.

 B에 생성자를 만들었지만 부모 클래스인 A class가 호출이 되며

1. A()

2. this(3) =  A(3) -> "A 생성자 3"

3. A() -> "A 생성자 입니다."

4. B()

5. this(45) = B(45) -> "B 생성자 2-45입니다."

6. B() -> "B 생성자입니다."

 

B()만 호출이 되는 것이 아니라 부모클래스가 호출이 된다.

모든 생성자의 첫 줄에는 반드시 this() 혹은 super()가 있어야한다

출력값:


2. Abstract (추상 클래스)

- 추상 클래스는 자식클래스에 상속되며 자식 클래스에 의해서 완성 가능

- 클래스 = 설계도, 추상클래스 = 미완성된 설계도

- 추상 클래스는 여러 개의 자식 클래스들에서 공통적인 필드나 메서도를 추출해서 만들 수 있다

 

ex)

1. 고양이, 개, 소 등이 있다.

2. 고양이도 울고, 개도 울고, 소도 운다.

3. 그럼 거기에 대해서 전부 메소드를 통해 구현하는가? - > X

4. 고양이, 개, 소는 동물이다.

5. 동물이라는 추상클래스를 만들어서 구현하면 된다.

// 동물이라는 추상 클래스
public abstract class 동물 {
    abstract void cry();
}
public class 고양이 extends 동물 {
    @Override
    public void cry() {
        System.out.print("야옹");	
    }
}
public class 개 extends 동물 {
    @Override
    public void cry() {
        System.out.print("멍");	
    }
}

3. Interface 

- 두 객체를 연결해주는 다리 역할

- 삼성 티비, 엘지 티비는 상속관계가 없다. 하지만 리모콘으로 채널을 변경, 음향을 조절하는데는 문제 X

public class LgTv extends Tv implements MultiRemoteController {

    public LgTv(String company) {
        super(company);
    }

    @Override
    public void turnOnOff() {
        setPower(!isPower());
        displayPower(getCompany(), isPower());
    }

    @Override
    public void channelUp() {
        setChannel(getChannel() + 1);
        displayChannel(getChannel());
    }

    @Override
    public void channelDown() {
        setChannel(getChannel() - 1);
        displayChannel(getChannel());
    }

    @Override
    public void volumeUp() {
        setVolume(getVolume() + 1);
        displayVolume(getVolume());
    }

    @Override
    public void volumeDown() {
        setVolume(getVolume() - 1);
        displayVolume(getVolume());
    }
}
public interface MultiRemoteController {

    void turnOnOff();
    void channelUp();
    void channelDown();
    void volumeUp();
    void volumeDown();

    // 매개변수와 반환타입 다형성 확인 메서드
    default MultiRemoteController getTV(Tv tv) {
        if(tv instanceof SamsungTv) {
            return (SamsungTv) tv;
        } else if(tv instanceof LgTv){
            return (LgTv) tv;
        } else {
            throw new NullPointerException("일치하는 Tv 없음");
        }
    }

}
public class Main {
    public static void main(String[] args) {

        // LG TV 구현체를 조작
        MultiRemoteController mrc = new LgTv("LG");
        mrc.turnOnOff();
        mrc.volumeUp();
        mrc.channelDown();
        mrc.channelUp();
        mrc.turnOnOff();
        
        }
}

-> 이런것이 가능한 이유 "다형성" -> 여러 가지 형태를 가질 수 있는 능력


4. 클래스 설계해보기

 

맞는 설계는 아닌 것 같지만 게임을 대충 만든다고 생각하면

- Monster와 User가 있고, hp, mp, attackPower 등 여러가지 필드가 공통적으로 들어간다.

-> Character에게 상속

- Monster는 여러가지 종류가 있다.

-> Slime, Goblin이 Monster에게 상속

- 플레이어와 몬스터는 상속관계를 가지지 않지만 서로 동일한 행위, 필드를 가지고 있다.

-> UserMonsterController라는 인터페이스를 통해 제어

 

=> 물론 코드로 게임을 구현하지는 못했지만 설계를 대략으로 해보니

인스턴스, 클래스, 추상화 등이 감이 잡히기 시작한다.


5. 스파르타 종합반 3주차 숙제 재분석

부끄럽지만 숙제가 무슨 말인지 모르겠다. 다시 말해 이해가 안 가는 부분이 많았다.

그래서 1시간 고민 뒤, 정답 코드를 열어보았다. 역시나 무슨 말인지 이해가 안 간다.

 

결국 해설 영상까지 돌려 보았다. 한 40% 정도 이해한 것 같다.

하지만 이해 안 가는 부분이 많아 정리해보았다.


step 3.

- AddOperation, SubstractOperation, MultiplyOperation, DivideOperation 연산 클래스들을 만듭니다. Calculator 클래스와 포함관계를 맺고 생성자를 통해 각각의 연산 클래스 타입의 필드에 객체를 주입합니다.

-> 포함관계, 객체를 주입 -> 이게 무슨 말인지 이해가 안 갔다.

 

step 4.

- Calculator 클래스는 4개의 연산 클래스들이 상속받고 있는 AbstractOperation 클래스만을 포함합니다.

-> ??? 이게 무슨 말인가

 

- 생성자 혹은 Setter를 사용하여 연산을 수행할 연산 클래스의 객체를 AbstractOperation 클래스 타입의 필드에 주입합니다.(다형성)

-> 주입 한다는 말과 다형성... 아직 다형성에 대해 이해하지 못하였을 때이다.

 

- calculate 메서드에서는 더 이상 연산자 타입을 받아 구분할 필요 없이 주입 받은 연산 클래스의 operate 메서드를 통해 바로 연산을 수행합니다.

-> 주입이라는 말이 계속 나온다. 이걸 어떻게 이해해야 할까?


그래서 모르는 부분은 튜터님에게 찾아가 여쭤보았더니 이제야 좀 이해가 가기 시작한다. 70%


step 3.

- AddOperation, SubstractOperation, MultiplyOperation, DivideOperation 연산 클래스들을 만듭니다. Calculator 클래스와 포함관계를 맺고 생성자를 통해 각각의 연산 클래스 타입의 필드에 객체를 주입합니다.

-> 말 그대로 생성자에 객체를 넣어준다는 말이며, 저 4개의 객체를 Calculator를 만들 때, 넣어준다. 그리고 필드에 선언하여 Calculator에서 그 객체의 메소드를 호출할 수 있게 하는 것이다.

 

step 4.

- Calculator 클래스는 4개의 연산 클래스들이 상속받고 있는 AbstractOperation 클래스만을 포함합니다.

-> 각 연산 클래스는 비슷한 입출력형태를 가지고 있기에 추상클래스로 정리될 수 있음. 입출력 고정 가능

 

- 생성자 혹은 Setter를 사용하여 연산을 수행할 연산 클래스의 객체를 AbstractOperation 클래스 타입의 필드에 주입합니다.(다형성)

-> 말 그대로 생성할 때, 생성자에 원하는 계산의 객체를 넣고 추상 클래스는 다형성을 가지니까 문제가 없다. 그 추상클래스는 필드에 들어가 원하는 연산이 가능하게 한다.

 

- calculate 메서드에서는 더 이상 연산자 타입을 받아 구분할 필요 없이 주입 받은 연산 클래스의 operate 메서드를 통해 바로 연산을 수행합니다.

-> Calculator에서는 연산자를 따로 필요하지 않고, 객체를 통해 구분하고 각 객체의 operate 함수에 숫자를 넣어 계산한다.

 


클래스 정말 어렵다. 머리가 고장난 것 같다.

옛날에 프로젝트 할 때, 이런 것도 이해하지 못하고 만든 것이 후회스럽다. 이러한 패턴, 추상화에 대해서는 계속 공부해야 될 것 같다.