Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 134 additions & 0 deletions TIL/sample/2026-06-15.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# 2026-06-15

## 오늘 배운 내용

### 1. 캡슐화

- 캡슐화는 필드를 외부에서 직접 변경하지 못하게 숨기고, 메소드를 통해 안전하게 접근하도록 만드는 것이다.
- 필드는 보통 `private`으로 선언한다.
- 값을 읽을 때는 getter, 값을 변경할 때는 setter를 사용한다.
- setter 안에서 잘못된 값이 들어오지 않도록 검사를 할 수 있다.
- 잘못된 값이 들어오면 `IllegalArgumentException`을 발생시켜 프로그램을 중단할 수 있다.

```java
public void setName(String name) {
if (name == null || name.length() < 3) {
throw new IllegalArgumentException("이름은 null일 수 없고 3문자 이상이어야 합니다.");
}
this.name = name;
}
```

### 2. 객체가 자기 값을 책임진다

- `Wand`는 지팡이의 이름과 마력을 스스로 검사한다.
- `Wizard`는 마법사의 이름, HP, MP, 지팡이 장착 여부를 스스로 검사한다.
- `Wizard.setWand()`에서 지팡이 이름이나 마력까지 다시 검사할 필요는 없다.
- 지팡이의 상태는 `Wand`가 책임지고, 마법사의 상태는 `Wizard`가 책임진다.

```java
public void setWand(Wand wand) {
if (wand == null) {
throw new IllegalArgumentException("마법사의 지팡이는 null일 수 없습니다.");
}
this.wand = wand;
}
```

### 3. List, Set, Map

- `List`
- 순서가 있다.
- 중복을 허용한다.
- 예: 학생 10명의 시험 점수

- `Set`
- 순서가 중요하지 않다.
- 중복을 허용하지 않는다.
- 예: 대한민국의 도시 이름 모음

- `Map`
- key와 value를 한 쌍으로 저장한다.
- 예: 도시별 인구수, 이름별 나이

```java
Map<String, Integer> ages = new LinkedHashMap<>();

ages.put("홍길동", 20);
ages.put("한석봉", 25);
```

## 기억할 것

### 캡슐화

- 필드는 직접 접근하지 못하게 `private`으로 만든다.
- 외부에서는 getter와 setter를 통해 접근한다.
- setter는 단순히 값을 넣는 역할만 하는 것이 아니라, 값이 올바른지 검사하는 역할도 한다.

```java
private int mp;

public void setMp(int mp) {
if (mp < 0) {
throw new IllegalArgumentException("MP는 0 이상이어야 합니다.");
}
this.mp = mp;
}
```

### 컬렉션 선택 기준


| 기준 | 컬렉션 |
|--|---|
| `List` | 중복을 허용하고 순서가 필요하면 |
|`Set` | 중복을 막고 싶으면|
|`Map` | 이름과 나이처럼 쌍으로 저장하면|


## 실습 코드

### Person 리스트

```java
List<Person> people = new ArrayList<>();

people.add(new Person("홍길동"));
people.add(new Person("한석봉"));

for (Person person : people) {
System.out.println(person.getName());
}
```

### 이름과 나이를 Map에 저장

```java
Map<String, Integer> ages = new LinkedHashMap<>();

ages.put("홍길동", 20);
ages.put("한석봉", 25);

for (Map.Entry<String, Integer> entry : ages.entrySet()) {
System.out.println(entry.getKey() + "의 나이는 " + entry.getValue() + "살");
}
```

## 어려웠던 점

- 처음에는 `private`으로 필드를 숨기면 코드가 더 복잡해지는 것처럼 느껴졌다.
- 하지만 setter에서 잘못된 값을 막을 수 있어서 객체의 상태를 안전하게 유지할 수 있다는 점을 알게 되었다.
- `List`, `Set`, `Map`은 이름은 익숙했지만, 어떤 상황에서 무엇을 써야 하는지 구분하는 것이 헷갈렸다.

## 해결 방법

- 값 하나하나를 어디서 검사해야 하는지 생각했다.
- `Wand`의 값은 `Wand`가 검사하고, `Wizard`의 값은 `Wizard`가 검사하도록 나누었다.
- 컬렉션은 저장하려는 데이터의 특징을 먼저 보고 골랐다.

## 내일 더 공부할 것

- 상속
- 오버라이딩
- 추상 클래스
241 changes: 241 additions & 0 deletions TIL/sample/2026-06-16.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
# 2026-06-16

## 오늘 배운 내용

### 1. 오버라이딩

- 오버라이딩은 부모 클래스가 가진 메서드를 자식 클래스에서 다시 정의하는 것이다.
- 자식 클래스는 부모 클래스의 기능을 그대로 물려받을 수 있지만, 필요하면 자신의 상황에 맞게 메서드 내용을 바꿀 수 있다.
- 오버라이딩을 할 때는 부모 메서드와 이름, 매개변수, 리턴 타입이 같아야 한다.
- 오버라이딩한 메서드 위에는 `@Override`를 붙이는 것이 좋다.
- `@Override`를 붙이면 메서드 이름이나 매개변수를 잘못 작성했을 때 컴파일러가 알려준다.

```java
class Wizard {
public void heal(Hero hero) {
hero.setHp(hero.getHp() + 20);
}
}

class GreatWizard extends Wizard {
@Override
public void heal(Hero hero) {
hero.setHp(hero.getHp() + 25);
}
}
```

### 2. 부모 메서드 호출

- 자식 클래스에서 오버라이딩을 했더라도 부모의 메서드를 호출할 수 있다.
- 이때 `super.메서드명()`을 사용한다.
- 부모의 기본 동작을 먼저 실행하고, 자식 클래스에서 추가 동작을 붙이고 싶을 때 사용한다.

```java
class Slime {
public void attack(Hero hero) {
hero.setHp(hero.getHp() - 10);
}
}

class PoisonSlime extends Slime {
@Override
public void attack(Hero hero) {
super.attack(hero);

int poisonDamage = hero.getHp() / 5;
hero.setHp(hero.getHp() - poisonDamage);
}
}
```

### 3. 오버라이딩과 다형성

- 부모 타입 변수에 자식 인스턴스를 담을 수 있다.
- 이때 메서드를 호출하면 실제 인스턴스의 오버라이딩된 메서드가 실행된다.
- 이것을 다형성이라고 한다.

```java
Wizard wizard = new GreatWizard();

wizard.heal(hero); // GreatWizard의 heal() 실행
```

## 기억할 것

### 오버로딩과 오버라이딩 차이

| 구분 | 오버로딩 | 오버라이딩 |
|---|---|---|
| 관계 | 같은 클래스 안에서 사용 | 상속 관계에서 사용 |
| 메서드 이름 | 같아야 함 | 같아야 함 |
| 매개변수 | 달라야 함 | 같아야 함 |
| 리턴 타입 | 상관없지만 리턴 타입만 다르면 안 됨 | 같아야 함 |
| 목적 | 같은 이름으로 여러 기능 제공 | 부모 기능을 자식 방식으로 변경 |

### `@Override`

- 오버라이딩한 메서드에는 `@Override`를 붙인다.
- 오타나 매개변수 차이로 오버라이딩이 안 되는 실수를 막을 수 있다.

```java
@Override
public void attack(Hero hero) {
super.attack(hero);
}
```

### `super`

- `super`는 부모 클래스를 가리킨다.
- `super.attack(hero)`처럼 사용하면 부모 클래스의 메서드를 실행할 수 있다.
- 부모의 기능을 유지하면서 자식 클래스의 기능을 추가할 때 유용하다.

## 실습 코드

### Wizard와 GreatWizard

```java
package com.survivalcoding.day260616;

public abstract class Wizard {
private int mp = 100;

public void heal(Hero hero) {
int recovPoint = 20;

if (this.mp < 10) {
System.out.println("마나가 부족합니다");
return;
}

hero.setHp(hero.getHp() + recovPoint);
setMp(getMp() - 10);
System.out.println("힐을 시전했습니다. 대상 HP : " + hero.getHp());
}

public int getMp() {
return mp;
}

public void setMp(int mp) {
if (mp < 0) {
throw new IllegalArgumentException("마법사의 MP는 0 이상이어야 합니다.");
}
this.mp = mp;
}
}
```

```java
package com.survivalcoding.day260616;

public class GreatWizard extends Wizard {
public GreatWizard() {
setMp(150);
}
Comment on lines +133 to +136

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

실습 코드 예시가 실제 구현과 달라 학습 포인트를 혼동시킬 수 있습니다.

GreatWizard 생성자 예시가 실제 코드(super(150))와 달라서, 상속 생성자 체이닝 학습 맥락이 어긋납니다. 문서 예시를 실제 구현과 맞춰 주세요.

문서 예시 정합성 수정안
 public class GreatWizard extends Wizard {
     public GreatWizard() {
-        setMp(150);
+        super(150);
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public class GreatWizard extends Wizard {
public GreatWizard() {
setMp(150);
}
public class GreatWizard extends Wizard {
public GreatWizard() {
super(150);
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@TIL/sample/2026-06-16.md` around lines 133 - 136, The GreatWizard constructor
example in the documentation uses setMp(150) but the actual implementation uses
super(150). Update the constructor example in the GreatWizard class to use
super(150) instead of setMp(150) to align the documentation with the actual
implementation and maintain consistency in demonstrating inheritance constructor
chaining patterns.


@Override
public void heal(Hero hero) {
int recovPoint = 25;

if (getMp() < 5) {
System.out.println("마나가 부족합니다");
return;
}

hero.setHp(hero.getHp() + recovPoint);
setMp(getMp() - 5);
System.out.println("힐을 시전했습니다. 대상 HP : " + hero.getHp());
}

public void superHeal(Hero hero) {
if (getMp() < 50) {
System.out.println("마나가 부족합니다");
return;
}

hero.setHp(hero.getMaxHp());
setMp(getMp() - 50);
System.out.println("슈퍼 힐을 시전했습니다. 대상 HP : " + hero.getHp());
}
}
```

### Slime과 PoisonSlime

```java
package com.survivalcoding.day260616;

public class Slime {
private final String suffix = "slime";
private String name;
private int hp = 40;

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

public void attack(Hero hero) {
System.out.println("슬라임" + suffix + "이/가 공격했다");
System.out.println("10의 데미지");

hero.setHp(hero.getHp() - 10);
}
}
```

```java
package com.survivalcoding.day260616;

public class PoisonSlime extends Slime {
private int poisonCount = 5;

public PoisonSlime(String name) {
super(name);
}

@Override
public void attack(Hero hero) {
super.attack(hero);

if (this.poisonCount > 0) {
System.out.println("추가로, 독 포자를 살포했다!");

int poisonDamage = hero.getHp() / 5;
hero.setHp(hero.getHp() - poisonDamage);

System.out.println(poisonDamage + "포인트 데미지!");

this.poisonCount -= 1;
}
}
}
```

## 어려웠던 점

- 오버라이딩은 부모 메서드와 이름, 매개변수, 리턴 타입이 같아야 한다는 점이 중요했다.
- 자식 클래스에서 부모 클래스의 필드를 또 만들면 값이 따로 관리될 수 있다는 점이 헷갈렸다.
- 예를 들어 부모에도 `mp`가 있고 자식에도 `mp`가 있으면 `getMp()`와 `this.mp`가 서로 다른 값을 볼 수 있다.

## 해결 방법

- 오버라이딩할 때는 항상 `@Override`를 붙여서 실수를 줄였다.
- 부모의 기능을 먼저 사용해야 하는 경우에는 `super.attack(hero)`처럼 `super`를 사용했다.
- 자식 클래스에서는 부모와 같은 필드를 다시 만들지 않고, 부모의 getter와 setter를 사용하도록 정리했다.

```java
if (getMp() < 5) {
System.out.println("마나가 부족합니다");
return;
}

setMp(getMp() - 5);
```

## 내일 더 공부할 것

- 추상 클래스
- 인터페이스
- 다형성
Loading